1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex *) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 if (markers) { 167 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 168 } 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for (v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for (e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for (c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = PETSC_NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm = ((PetscObject) dm)->comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 284 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 285 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 286 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 287 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 288 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 289 if (depth == 1) { 290 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 291 pEnd = pEnd - pStart; 292 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 293 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 294 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 295 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 296 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 297 pEnd = pEnd - pStart; 298 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 299 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 300 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 301 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 302 } else { 303 for (d = 0; d <= dim; d++) { 304 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 305 pEnd = pEnd - pStart; 306 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 307 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 308 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 309 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 310 } 311 } 312 ierr = PetscFree(sizes);CHKERRQ(ierr); 313 } 314 PetscFunctionReturn(0); 315 } 316 317 #undef __FUNCT__ 318 #define __FUNCT__ "DMView_Plex" 319 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 320 { 321 PetscBool iascii, isbinary; 322 PetscErrorCode ierr; 323 324 PetscFunctionBegin; 325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 326 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 327 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 329 if (iascii) { 330 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 331 #if 0 332 } else if (isbinary) { 333 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 334 #endif 335 } 336 PetscFunctionReturn(0); 337 } 338 339 #undef __FUNCT__ 340 #define __FUNCT__ "DMDestroy_Plex" 341 PetscErrorCode DMDestroy_Plex(DM dm) 342 { 343 DM_Plex *mesh = (DM_Plex *) dm->data; 344 DMLabel next = mesh->labels; 345 PetscErrorCode ierr; 346 347 PetscFunctionBegin; 348 if (--mesh->refct > 0) {PetscFunctionReturn(0);} 349 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 350 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 352 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 353 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 355 while (next) { 356 DMLabel tmp = next->next; 357 358 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 359 next = tmp; 360 } 361 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 362 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 364 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 365 ierr = PetscFree(mesh);CHKERRQ(ierr); 366 PetscFunctionReturn(0); 367 } 368 369 #undef __FUNCT__ 370 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 371 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 372 { 373 const PetscInt *support = PETSC_NULL; 374 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 375 PetscErrorCode ierr; 376 377 PetscFunctionBegin; 378 if (useClosure) { 379 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 380 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 381 for (s = 0; s < supportSize; ++s) { 382 const PetscInt *cone = PETSC_NULL; 383 PetscInt coneSize, c, q; 384 385 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 386 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 387 for (c = 0; c < coneSize; ++c) { 388 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 389 if (cone[c] == adj[q]) break; 390 } 391 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 392 } 393 } 394 } else { 395 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 396 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 397 for (s = 0; s < supportSize; ++s) { 398 const PetscInt *cone = PETSC_NULL; 399 PetscInt coneSize, c, q; 400 401 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 402 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 403 for (c = 0; c < coneSize; ++c) { 404 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 405 if (cone[c] == adj[q]) break; 406 } 407 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 408 } 409 } 410 } 411 *adjSize = numAdj; 412 PetscFunctionReturn(0); 413 } 414 415 #undef __FUNCT__ 416 #define __FUNCT__ "DMPlexGetAdjacency_Private" 417 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 418 { 419 const PetscInt *star = tmpClosure; 420 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 421 PetscErrorCode ierr; 422 423 PetscFunctionBegin; 424 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr); 425 for (s = 2; s < starSize*2; s += 2) { 426 const PetscInt *closure = PETSC_NULL; 427 PetscInt closureSize, c, q; 428 429 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 430 for (c = 0; c < closureSize*2; c += 2) { 431 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 432 if (closure[c] == adj[q]) break; 433 } 434 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 435 } 436 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 437 } 438 *adjSize = numAdj; 439 PetscFunctionReturn(0); 440 } 441 442 #undef __FUNCT__ 443 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 444 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 445 { 446 DM_Plex *mesh = (DM_Plex *) dm->data; 447 448 PetscFunctionBegin; 449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 450 mesh->preallocCenterDim = preallocCenterDim; 451 PetscFunctionReturn(0); 452 } 453 454 #undef __FUNCT__ 455 #define __FUNCT__ "DMPlexPreallocateOperator" 456 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 457 { 458 DM_Plex *mesh = (DM_Plex *) dm->data; 459 MPI_Comm comm = ((PetscObject) dm)->comm; 460 PetscSF sf, sfDof, sfAdj; 461 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 462 PetscInt nleaves, l, p; 463 const PetscInt *leaves; 464 const PetscSFNode *remotes; 465 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 466 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 467 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 468 PetscLayout rLayout; 469 PetscInt locRows, rStart, rEnd, r; 470 PetscMPIInt size; 471 PetscBool useClosure, debug = PETSC_FALSE; 472 PetscErrorCode ierr; 473 474 PetscFunctionBegin; 475 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 476 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 477 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 478 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 479 /* Create dof SF based on point SF */ 480 if (debug) { 481 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 487 } 488 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 489 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 490 if (debug) { 491 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 492 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 493 } 494 /* Create section for dof adjacency (dof ==> # adj dof) */ 495 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 496 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 497 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 498 if (mesh->preallocCenterDim == dim) { 499 useClosure = PETSC_FALSE; 500 } else if (mesh->preallocCenterDim == 0) { 501 useClosure = PETSC_TRUE; 502 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 503 504 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 505 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 510 /* Fill in the ghost dofs on the interface */ 511 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 512 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 513 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 514 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 515 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 516 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 517 518 /* 519 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 520 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 521 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 522 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 523 Create sfAdj connecting rootSectionAdj and leafSectionAdj 524 3. Visit unowned points on interface, write adjacencies to adj 525 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 526 4. Visit owned points on interface, write adjacencies to rootAdj 527 Remove redundancy in rootAdj 528 ** The last two traversals use transitive closure 529 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 530 Allocate memory addressed by sectionAdj (cols) 531 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 532 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 533 */ 534 535 for (l = 0; l < nleaves; ++l) { 536 PetscInt dof, off, d, q; 537 PetscInt p = leaves[l], numAdj = maxAdjSize; 538 539 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 540 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 541 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 542 for (q = 0; q < numAdj; ++q) { 543 PetscInt ndof, ncdof; 544 545 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 546 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 547 for (d = off; d < off+dof; ++d) { 548 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 549 } 550 } 551 } 552 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 553 if (debug) { 554 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 555 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 556 } 557 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 558 if (size > 1) { 559 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 560 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 561 } 562 if (debug) { 563 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 564 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 565 } 566 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 567 for (p = pStart; p < pEnd; ++p) { 568 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 569 570 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 571 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 572 if (!dof) continue; 573 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 574 if (adof <= 0) continue; 575 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 576 for (q = 0; q < numAdj; ++q) { 577 PetscInt ndof, ncdof; 578 579 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 580 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 581 for (d = off; d < off+dof; ++d) { 582 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 583 } 584 } 585 } 586 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 587 if (debug) { 588 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 589 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 590 } 591 /* Create adj SF based on dof SF */ 592 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 593 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 594 if (debug) { 595 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 596 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 597 } 598 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 599 /* Create leaf adjacency */ 600 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 601 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 602 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 603 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 604 for (l = 0; l < nleaves; ++l) { 605 PetscInt dof, off, d, q; 606 PetscInt p = leaves[l], numAdj = maxAdjSize; 607 608 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 609 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 610 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 611 for (d = off; d < off+dof; ++d) { 612 PetscInt aoff, i = 0; 613 614 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 615 for (q = 0; q < numAdj; ++q) { 616 PetscInt ndof, ncdof, ngoff, nd; 617 618 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 619 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 620 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 621 for (nd = 0; nd < ndof-ncdof; ++nd) { 622 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 623 ++i; 624 } 625 } 626 } 627 } 628 /* Debugging */ 629 if (debug) { 630 IS tmp; 631 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 632 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 633 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 634 } 635 /* Gather adjacenct indices to root */ 636 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 637 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 638 for (r = 0; r < adjSize; ++r) { 639 rootAdj[r] = -1; 640 } 641 if (size > 1) { 642 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 643 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 644 } 645 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 646 ierr = PetscFree(adj);CHKERRQ(ierr); 647 /* Debugging */ 648 if (debug) { 649 IS tmp; 650 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 651 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 652 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 653 } 654 /* Add in local adjacency indices for owned dofs on interface (roots) */ 655 for (p = pStart; p < pEnd; ++p) { 656 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 657 658 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 659 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 660 if (!dof) continue; 661 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 662 if (adof <= 0) continue; 663 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 664 for (d = off; d < off+dof; ++d) { 665 PetscInt adof, aoff, i; 666 667 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 668 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 669 i = adof-1; 670 for (q = 0; q < numAdj; ++q) { 671 PetscInt ndof, ncdof, ngoff, nd; 672 673 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 674 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 675 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 676 for (nd = 0; nd < ndof-ncdof; ++nd) { 677 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 678 --i; 679 } 680 } 681 } 682 } 683 /* Debugging */ 684 if (debug) { 685 IS tmp; 686 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 687 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 688 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 689 } 690 /* Compress indices */ 691 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 692 for (p = pStart; p < pEnd; ++p) { 693 PetscInt dof, cdof, off, d; 694 PetscInt adof, aoff; 695 696 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 697 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 698 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 699 if (!dof) continue; 700 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 701 if (adof <= 0) continue; 702 for (d = off; d < off+dof-cdof; ++d) { 703 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 704 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 705 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 706 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 707 } 708 } 709 /* Debugging */ 710 if (debug) { 711 IS tmp; 712 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 713 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 714 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 715 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 716 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 717 } 718 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 719 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 720 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 721 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 722 for (p = pStart; p < pEnd; ++p) { 723 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 724 PetscBool found = PETSC_TRUE; 725 726 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 727 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 728 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 729 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 730 for (d = 0; d < dof-cdof; ++d) { 731 PetscInt ldof, rdof; 732 733 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 734 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 735 if (ldof > 0) { 736 /* We do not own this point */ 737 } else if (rdof > 0) { 738 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 739 } else { 740 found = PETSC_FALSE; 741 } 742 } 743 if (found) continue; 744 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 745 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 746 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 747 for (q = 0; q < numAdj; ++q) { 748 PetscInt ndof, ncdof, noff; 749 750 /* Adjacent points may not be in the section chart */ 751 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 752 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 753 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 754 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 755 for (d = goff; d < goff+dof-cdof; ++d) { 756 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 757 } 758 } 759 } 760 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 761 if (debug) { 762 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 763 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 764 } 765 /* Get adjacent indices */ 766 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 767 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 768 for (p = pStart; p < pEnd; ++p) { 769 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 770 PetscBool found = PETSC_TRUE; 771 772 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 773 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 774 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 775 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 776 for (d = 0; d < dof-cdof; ++d) { 777 PetscInt ldof, rdof; 778 779 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 780 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 781 if (ldof > 0) { 782 /* We do not own this point */ 783 } else if (rdof > 0) { 784 PetscInt aoff, roff; 785 786 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 787 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 788 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 789 } else { 790 found = PETSC_FALSE; 791 } 792 } 793 if (found) continue; 794 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 795 for (d = goff; d < goff+dof-cdof; ++d) { 796 PetscInt adof, aoff, i = 0; 797 798 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 799 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 800 for (q = 0; q < numAdj; ++q) { 801 PetscInt ndof, ncdof, ngoff, nd; 802 const PetscInt *ncind; 803 804 /* Adjacent points may not be in the section chart */ 805 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 806 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 807 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 808 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 809 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 810 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 811 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 812 } 813 } 814 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 815 } 816 } 817 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 818 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 819 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 820 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 821 /* Debugging */ 822 if (debug) { 823 IS tmp; 824 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 825 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 826 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 827 } 828 /* Create allocation vectors from adjacency graph */ 829 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 830 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 831 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 832 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 833 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 834 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 835 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 836 /* Only loop over blocks of rows */ 837 if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 838 for (r = rStart/bs; r < rEnd/bs; ++r) { 839 const PetscInt row = r*bs; 840 PetscInt numCols, cStart, c; 841 842 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 843 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 844 for (c = cStart; c < cStart+numCols; ++c) { 845 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 846 ++dnz[r-rStart]; 847 if (cols[c] >= row) {++dnzu[r-rStart];} 848 } else { 849 ++onz[r-rStart]; 850 if (cols[c] >= row) {++onzu[r-rStart];} 851 } 852 } 853 } 854 if (bs > 1) { 855 for (r = 0; r < locRows/bs; ++r) { 856 dnz[r] /= bs; 857 onz[r] /= bs; 858 dnzu[r] /= bs; 859 onzu[r] /= bs; 860 } 861 } 862 /* Set matrix pattern */ 863 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 864 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 865 /* Fill matrix with zeros */ 866 if (fillMatrix) { 867 PetscScalar *values; 868 PetscInt maxRowLen = 0; 869 870 for (r = rStart; r < rEnd; ++r) { 871 PetscInt len; 872 873 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 874 maxRowLen = PetscMax(maxRowLen, len); 875 } 876 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 877 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 878 for (r = rStart; r < rEnd; ++r) { 879 PetscInt numCols, cStart; 880 881 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 882 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 883 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 884 } 885 ierr = PetscFree(values);CHKERRQ(ierr); 886 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 887 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 888 } 889 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 890 ierr = PetscFree(cols);CHKERRQ(ierr); 891 PetscFunctionReturn(0); 892 } 893 894 #if 0 895 #undef __FUNCT__ 896 #define __FUNCT__ "DMPlexPreallocateOperator_2" 897 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 898 { 899 PetscErrorCode ierr; 900 PetscInt c,cStart,cEnd,pStart,pEnd; 901 PetscInt *tmpClosure,*tmpAdj,*visits; 902 903 PetscFunctionBegin; 904 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 905 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 906 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 907 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 908 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 909 npoints = pEnd - pStart; 910 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 911 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 912 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 913 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 914 for (c=cStart; c<cEnd; c++) { 915 PetscInt *support = tmpClosure; 916 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 917 for (p=0; p<supportSize; p++) { 918 lvisits[support[p]]++; 919 } 920 } 921 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 922 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 923 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 924 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 925 926 ierr = PetscSFGetRanks();CHKERRQ(ierr); 927 928 929 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 930 for (c=cStart; c<cEnd; c++) { 931 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 932 /* 933 Depth-first walk of transitive closure. 934 At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 935 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 936 */ 937 } 938 939 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 940 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 941 PetscFunctionReturn(0); 942 } 943 #endif 944 945 #undef __FUNCT__ 946 #define __FUNCT__ "DMCreateMatrix_Plex" 947 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 948 { 949 PetscSection section, sectionGlobal; 950 PetscInt bs = -1; 951 PetscInt localSize; 952 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 953 PetscErrorCode ierr; 954 955 PetscFunctionBegin; 956 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 957 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 958 #endif 959 if (!mtype) mtype = MATAIJ; 960 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 961 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 962 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 963 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 964 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 965 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 966 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 967 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 968 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 974 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 975 /* Check for symmetric storage */ 976 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 977 if (isSymmetric) { 978 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 979 } 980 if (!isShell) { 981 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 982 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal; 983 984 if (bs < 0) { 985 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 986 PetscInt pStart, pEnd, p, dof; 987 988 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 989 for (p = pStart; p < pEnd; ++p) { 990 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 991 if (dof) { 992 bs = dof; 993 break; 994 } 995 } 996 } else { 997 bs = 1; 998 } 999 /* Must have same blocksize on all procs (some might have no points) */ 1000 bsLocal = bs; 1001 ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1002 } 1003 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1004 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1005 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1006 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1007 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1008 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1009 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1010 } 1011 PetscFunctionReturn(0); 1012 } 1013 1014 #undef __FUNCT__ 1015 #define __FUNCT__ "DMPlexGetDimension" 1016 /*@ 1017 DMPlexGetDimension - Return the topological mesh dimension 1018 1019 Not collective 1020 1021 Input Parameter: 1022 . mesh - The DMPlex 1023 1024 Output Parameter: 1025 . dim - The topological mesh dimension 1026 1027 Level: beginner 1028 1029 .seealso: DMPlexCreate() 1030 @*/ 1031 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1032 { 1033 DM_Plex *mesh = (DM_Plex *) dm->data; 1034 1035 PetscFunctionBegin; 1036 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1037 PetscValidPointer(dim, 2); 1038 *dim = mesh->dim; 1039 PetscFunctionReturn(0); 1040 } 1041 1042 #undef __FUNCT__ 1043 #define __FUNCT__ "DMPlexSetDimension" 1044 /*@ 1045 DMPlexSetDimension - Set the topological mesh dimension 1046 1047 Collective on mesh 1048 1049 Input Parameters: 1050 + mesh - The DMPlex 1051 - dim - The topological mesh dimension 1052 1053 Level: beginner 1054 1055 .seealso: DMPlexCreate() 1056 @*/ 1057 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1058 { 1059 DM_Plex *mesh = (DM_Plex *) dm->data; 1060 1061 PetscFunctionBegin; 1062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1063 PetscValidLogicalCollectiveInt(dm, dim, 2); 1064 mesh->dim = dim; 1065 mesh->preallocCenterDim = dim; 1066 PetscFunctionReturn(0); 1067 } 1068 1069 #undef __FUNCT__ 1070 #define __FUNCT__ "DMPlexGetChart" 1071 /*@ 1072 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1073 1074 Not collective 1075 1076 Input Parameter: 1077 . mesh - The DMPlex 1078 1079 Output Parameters: 1080 + pStart - The first mesh point 1081 - pEnd - The upper bound for mesh points 1082 1083 Level: beginner 1084 1085 .seealso: DMPlexCreate(), DMPlexSetChart() 1086 @*/ 1087 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1088 { 1089 DM_Plex *mesh = (DM_Plex *) dm->data; 1090 PetscErrorCode ierr; 1091 1092 PetscFunctionBegin; 1093 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1094 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1095 PetscFunctionReturn(0); 1096 } 1097 1098 #undef __FUNCT__ 1099 #define __FUNCT__ "DMPlexSetChart" 1100 /*@ 1101 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1102 1103 Not collective 1104 1105 Input Parameters: 1106 + mesh - The DMPlex 1107 . pStart - The first mesh point 1108 - pEnd - The upper bound for mesh points 1109 1110 Output Parameters: 1111 1112 Level: beginner 1113 1114 .seealso: DMPlexCreate(), DMPlexGetChart() 1115 @*/ 1116 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1117 { 1118 DM_Plex *mesh = (DM_Plex *) dm->data; 1119 PetscErrorCode ierr; 1120 1121 PetscFunctionBegin; 1122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1123 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1124 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1125 PetscFunctionReturn(0); 1126 } 1127 1128 #undef __FUNCT__ 1129 #define __FUNCT__ "DMPlexGetConeSize" 1130 /*@ 1131 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1132 1133 Not collective 1134 1135 Input Parameters: 1136 + mesh - The DMPlex 1137 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1138 1139 Output Parameter: 1140 . size - The cone size for point p 1141 1142 Level: beginner 1143 1144 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1145 @*/ 1146 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1147 { 1148 DM_Plex *mesh = (DM_Plex *) dm->data; 1149 PetscErrorCode ierr; 1150 1151 PetscFunctionBegin; 1152 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1153 PetscValidPointer(size, 3); 1154 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1155 PetscFunctionReturn(0); 1156 } 1157 1158 #undef __FUNCT__ 1159 #define __FUNCT__ "DMPlexSetConeSize" 1160 /*@ 1161 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1162 1163 Not collective 1164 1165 Input Parameters: 1166 + mesh - The DMPlex 1167 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1168 - size - The cone size for point p 1169 1170 Output Parameter: 1171 1172 Note: 1173 This should be called after DMPlexSetChart(). 1174 1175 Level: beginner 1176 1177 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1178 @*/ 1179 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1180 { 1181 DM_Plex *mesh = (DM_Plex *) dm->data; 1182 PetscErrorCode ierr; 1183 1184 PetscFunctionBegin; 1185 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1186 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1187 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1188 PetscFunctionReturn(0); 1189 } 1190 1191 #undef __FUNCT__ 1192 #define __FUNCT__ "DMPlexGetCone" 1193 /*@C 1194 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1195 1196 Not collective 1197 1198 Input Parameters: 1199 + mesh - The DMPlex 1200 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1201 1202 Output Parameter: 1203 . cone - An array of points which are on the in-edges for point p 1204 1205 Level: beginner 1206 1207 Note: 1208 This routine is not available in Fortran. 1209 1210 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1211 @*/ 1212 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1213 { 1214 DM_Plex *mesh = (DM_Plex *) dm->data; 1215 PetscInt off; 1216 PetscErrorCode ierr; 1217 1218 PetscFunctionBegin; 1219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1220 PetscValidPointer(cone, 3); 1221 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1222 *cone = &mesh->cones[off]; 1223 PetscFunctionReturn(0); 1224 } 1225 1226 #undef __FUNCT__ 1227 #define __FUNCT__ "DMPlexSetCone" 1228 /*@ 1229 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1230 1231 Not collective 1232 1233 Input Parameters: 1234 + mesh - The DMPlex 1235 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1236 - cone - An array of points which are on the in-edges for point p 1237 1238 Output Parameter: 1239 1240 Note: 1241 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1242 1243 Level: beginner 1244 1245 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1246 @*/ 1247 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1248 { 1249 DM_Plex *mesh = (DM_Plex *) dm->data; 1250 PetscInt pStart, pEnd; 1251 PetscInt dof, off, c; 1252 PetscErrorCode ierr; 1253 1254 PetscFunctionBegin; 1255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1256 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1257 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1258 if (dof) PetscValidPointer(cone, 3); 1259 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1260 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1261 for (c = 0; c < dof; ++c) { 1262 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1263 mesh->cones[off+c] = cone[c]; 1264 } 1265 PetscFunctionReturn(0); 1266 } 1267 1268 #undef __FUNCT__ 1269 #define __FUNCT__ "DMPlexGetConeOrientation" 1270 /*@C 1271 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1272 1273 Not collective 1274 1275 Input Parameters: 1276 + mesh - The DMPlex 1277 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1278 1279 Output Parameter: 1280 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1281 integer giving the prescription for cone traversal. If it is negative, the cone is 1282 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1283 the index of the cone point on which to start. 1284 1285 Level: beginner 1286 1287 Note: 1288 This routine is not available in Fortran. 1289 1290 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1291 @*/ 1292 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1293 { 1294 DM_Plex *mesh = (DM_Plex *) dm->data; 1295 PetscInt off; 1296 PetscErrorCode ierr; 1297 1298 PetscFunctionBegin; 1299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1300 #if defined(PETSC_USE_DEBUG) 1301 { 1302 PetscInt dof; 1303 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1304 if (dof) PetscValidPointer(coneOrientation, 3); 1305 } 1306 #endif 1307 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1308 *coneOrientation = &mesh->coneOrientations[off]; 1309 PetscFunctionReturn(0); 1310 } 1311 1312 #undef __FUNCT__ 1313 #define __FUNCT__ "DMPlexSetConeOrientation" 1314 /*@ 1315 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1316 1317 Not collective 1318 1319 Input Parameters: 1320 + mesh - The DMPlex 1321 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1322 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1323 integer giving the prescription for cone traversal. If it is negative, the cone is 1324 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1325 the index of the cone point on which to start. 1326 1327 Output Parameter: 1328 1329 Note: 1330 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1331 1332 Level: beginner 1333 1334 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1335 @*/ 1336 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1337 { 1338 DM_Plex *mesh = (DM_Plex *) dm->data; 1339 PetscInt pStart, pEnd; 1340 PetscInt dof, off, c; 1341 PetscErrorCode ierr; 1342 1343 PetscFunctionBegin; 1344 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1345 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1346 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1347 if (dof) PetscValidPointer(coneOrientation, 3); 1348 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1349 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1350 for (c = 0; c < dof; ++c) { 1351 PetscInt cdof, o = coneOrientation[c]; 1352 1353 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1354 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1355 mesh->coneOrientations[off+c] = o; 1356 } 1357 PetscFunctionReturn(0); 1358 } 1359 1360 #undef __FUNCT__ 1361 #define __FUNCT__ "DMPlexInsertCone" 1362 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1363 { 1364 DM_Plex *mesh = (DM_Plex *) dm->data; 1365 PetscInt pStart, pEnd; 1366 PetscInt dof, off; 1367 PetscErrorCode ierr; 1368 1369 PetscFunctionBegin; 1370 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1371 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1372 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1373 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1374 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1375 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1376 if (conePos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1377 mesh->cones[off+conePos] = conePoint; 1378 PetscFunctionReturn(0); 1379 } 1380 1381 #undef __FUNCT__ 1382 #define __FUNCT__ "DMPlexGetSupportSize" 1383 /*@ 1384 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1385 1386 Not collective 1387 1388 Input Parameters: 1389 + mesh - The DMPlex 1390 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1391 1392 Output Parameter: 1393 . size - The support size for point p 1394 1395 Level: beginner 1396 1397 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1398 @*/ 1399 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1400 { 1401 DM_Plex *mesh = (DM_Plex *) dm->data; 1402 PetscErrorCode ierr; 1403 1404 PetscFunctionBegin; 1405 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1406 PetscValidPointer(size, 3); 1407 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1408 PetscFunctionReturn(0); 1409 } 1410 1411 #undef __FUNCT__ 1412 #define __FUNCT__ "DMPlexSetSupportSize" 1413 /*@ 1414 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1415 1416 Not collective 1417 1418 Input Parameters: 1419 + mesh - The DMPlex 1420 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1421 - size - The support size for point p 1422 1423 Output Parameter: 1424 1425 Note: 1426 This should be called after DMPlexSetChart(). 1427 1428 Level: beginner 1429 1430 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1431 @*/ 1432 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1433 { 1434 DM_Plex *mesh = (DM_Plex *) dm->data; 1435 PetscErrorCode ierr; 1436 1437 PetscFunctionBegin; 1438 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1439 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1440 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1441 PetscFunctionReturn(0); 1442 } 1443 1444 #undef __FUNCT__ 1445 #define __FUNCT__ "DMPlexGetSupport" 1446 /*@C 1447 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1448 1449 Not collective 1450 1451 Input Parameters: 1452 + mesh - The DMPlex 1453 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1454 1455 Output Parameter: 1456 . support - An array of points which are on the out-edges for point p 1457 1458 Level: beginner 1459 1460 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1461 @*/ 1462 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1463 { 1464 DM_Plex *mesh = (DM_Plex *) dm->data; 1465 PetscInt off; 1466 PetscErrorCode ierr; 1467 1468 PetscFunctionBegin; 1469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1470 PetscValidPointer(support, 3); 1471 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1472 *support = &mesh->supports[off]; 1473 PetscFunctionReturn(0); 1474 } 1475 1476 #undef __FUNCT__ 1477 #define __FUNCT__ "DMPlexSetSupport" 1478 /*@ 1479 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1480 1481 Not collective 1482 1483 Input Parameters: 1484 + mesh - The DMPlex 1485 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1486 - support - An array of points which are on the in-edges for point p 1487 1488 Output Parameter: 1489 1490 Note: 1491 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1492 1493 Level: beginner 1494 1495 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1496 @*/ 1497 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1498 { 1499 DM_Plex *mesh = (DM_Plex *) dm->data; 1500 PetscInt pStart, pEnd; 1501 PetscInt dof, off, c; 1502 PetscErrorCode ierr; 1503 1504 PetscFunctionBegin; 1505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1506 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1507 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1508 if (dof) PetscValidPointer(support, 3); 1509 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1510 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1511 for (c = 0; c < dof; ++c) { 1512 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1513 mesh->supports[off+c] = support[c]; 1514 } 1515 PetscFunctionReturn(0); 1516 } 1517 1518 #undef __FUNCT__ 1519 #define __FUNCT__ "DMPlexInsertSupport" 1520 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1521 { 1522 DM_Plex *mesh = (DM_Plex *) dm->data; 1523 PetscInt pStart, pEnd; 1524 PetscInt dof, off; 1525 PetscErrorCode ierr; 1526 1527 PetscFunctionBegin; 1528 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1529 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1530 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1531 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1532 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1533 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1534 if (supportPos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1535 mesh->supports[off+supportPos] = supportPoint; 1536 PetscFunctionReturn(0); 1537 } 1538 1539 #undef __FUNCT__ 1540 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1541 /*@C 1542 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1543 1544 Not collective 1545 1546 Input Parameters: 1547 + mesh - The DMPlex 1548 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1549 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1550 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1551 1552 Output Parameters: 1553 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1554 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1555 1556 Note: 1557 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1558 1559 Level: beginner 1560 1561 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1562 @*/ 1563 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1564 { 1565 DM_Plex *mesh = (DM_Plex *) dm->data; 1566 PetscInt *closure, *fifo; 1567 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1568 PetscInt tmpSize, t; 1569 PetscInt depth = 0, maxSize; 1570 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1571 PetscErrorCode ierr; 1572 1573 PetscFunctionBegin; 1574 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1575 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1576 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1577 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1578 if (*points) { 1579 closure = *points; 1580 } else { 1581 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1582 } 1583 closure[0] = p; closure[1] = 0; 1584 /* This is only 1-level */ 1585 if (useCone) { 1586 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1587 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1588 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1589 } else { 1590 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1591 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1592 } 1593 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1594 const PetscInt cp = tmp[t]; 1595 const PetscInt co = tmpO ? tmpO[t] : 0; 1596 1597 closure[closureSize] = cp; 1598 closure[closureSize+1] = co; 1599 fifo[fifoSize] = cp; 1600 fifo[fifoSize+1] = co; 1601 } 1602 while (fifoSize - fifoStart) { 1603 const PetscInt q = fifo[fifoStart]; 1604 const PetscInt o = fifo[fifoStart+1]; 1605 const PetscInt rev = o >= 0 ? 0 : 1; 1606 const PetscInt off = rev ? -(o+1) : o; 1607 1608 if (useCone) { 1609 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1610 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1611 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1612 } else { 1613 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1614 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1615 tmpO = PETSC_NULL; 1616 } 1617 for (t = 0; t < tmpSize; ++t) { 1618 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1619 const PetscInt cp = tmp[i]; 1620 /* Must propogate orientation */ 1621 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1622 PetscInt c; 1623 1624 /* Check for duplicate */ 1625 for (c = 0; c < closureSize; c += 2) { 1626 if (closure[c] == cp) break; 1627 } 1628 if (c == closureSize) { 1629 closure[closureSize] = cp; 1630 closure[closureSize+1] = co; 1631 fifo[fifoSize] = cp; 1632 fifo[fifoSize+1] = co; 1633 closureSize += 2; 1634 fifoSize += 2; 1635 } 1636 } 1637 fifoStart += 2; 1638 } 1639 if (numPoints) *numPoints = closureSize/2; 1640 if (points) *points = closure; 1641 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1642 PetscFunctionReturn(0); 1643 } 1644 1645 #undef __FUNCT__ 1646 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1647 /*@C 1648 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1649 1650 Not collective 1651 1652 Input Parameters: 1653 + mesh - The DMPlex 1654 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1655 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1656 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1657 1658 Output Parameters: 1659 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1660 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1661 1662 Note: 1663 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1664 1665 Level: beginner 1666 1667 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1668 @*/ 1669 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1670 { 1671 PetscErrorCode ierr; 1672 1673 PetscFunctionBegin; 1674 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1675 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1676 PetscFunctionReturn(0); 1677 } 1678 1679 #undef __FUNCT__ 1680 #define __FUNCT__ "DMPlexGetFaces" 1681 /* 1682 DMPlexGetFaces - 1683 1684 Note: This will only work for cell-vertex meshes. 1685 */ 1686 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1687 { 1688 DM_Plex *mesh = (DM_Plex *) dm->data; 1689 const PetscInt *cone = PETSC_NULL; 1690 PetscInt depth = 0, dim, coneSize; 1691 PetscErrorCode ierr; 1692 1693 PetscFunctionBegin; 1694 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1695 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1696 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1697 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1698 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1699 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1700 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1701 switch (dim) { 1702 case 2: 1703 switch (coneSize) { 1704 case 3: 1705 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1706 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1707 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1708 *numFaces = 3; 1709 *faceSize = 2; 1710 *faces = mesh->facesTmp; 1711 break; 1712 case 4: 1713 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1714 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1715 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1716 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1717 *numFaces = 4; 1718 *faceSize = 2; 1719 *faces = mesh->facesTmp; 1720 break; 1721 default: 1722 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1723 } 1724 break; 1725 case 3: 1726 switch (coneSize) { 1727 case 3: 1728 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1729 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1730 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1731 *numFaces = 3; 1732 *faceSize = 2; 1733 *faces = mesh->facesTmp; 1734 break; 1735 case 4: 1736 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1737 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1738 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1739 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1740 *numFaces = 4; 1741 *faceSize = 3; 1742 *faces = mesh->facesTmp; 1743 break; 1744 default: 1745 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1746 } 1747 break; 1748 default: 1749 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1750 } 1751 PetscFunctionReturn(0); 1752 } 1753 1754 #undef __FUNCT__ 1755 #define __FUNCT__ "DMPlexGetMaxSizes" 1756 /*@ 1757 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1758 1759 Not collective 1760 1761 Input Parameter: 1762 . mesh - The DMPlex 1763 1764 Output Parameters: 1765 + maxConeSize - The maximum number of in-edges 1766 - maxSupportSize - The maximum number of out-edges 1767 1768 Level: beginner 1769 1770 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1771 @*/ 1772 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1773 { 1774 DM_Plex *mesh = (DM_Plex *) dm->data; 1775 1776 PetscFunctionBegin; 1777 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1778 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1779 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1780 PetscFunctionReturn(0); 1781 } 1782 1783 #undef __FUNCT__ 1784 #define __FUNCT__ "DMSetUp_Plex" 1785 PetscErrorCode DMSetUp_Plex(DM dm) 1786 { 1787 DM_Plex *mesh = (DM_Plex *) dm->data; 1788 PetscInt size; 1789 PetscErrorCode ierr; 1790 1791 PetscFunctionBegin; 1792 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1793 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1794 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1795 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1796 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1797 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1798 if (mesh->maxSupportSize) { 1799 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1800 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1801 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1802 } 1803 PetscFunctionReturn(0); 1804 } 1805 1806 #undef __FUNCT__ 1807 #define __FUNCT__ "DMCreateSubDM_Plex" 1808 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1809 { 1810 PetscSection section, sectionGlobal; 1811 PetscInt *subIndices; 1812 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1813 PetscErrorCode ierr; 1814 1815 PetscFunctionBegin; 1816 if (!numFields) PetscFunctionReturn(0); 1817 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1818 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1819 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1820 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1821 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1822 if (numFields > nF) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1823 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1824 for (p = pStart; p < pEnd; ++p) { 1825 PetscInt gdof; 1826 1827 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1828 if (gdof > 0) { 1829 for (f = 0; f < numFields; ++f) { 1830 PetscInt fdof, fcdof; 1831 1832 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1833 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1834 subSize += fdof-fcdof; 1835 } 1836 } 1837 } 1838 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1839 for (p = pStart; p < pEnd; ++p) { 1840 PetscInt gdof, goff; 1841 1842 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1843 if (gdof > 0) { 1844 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1845 for (f = 0; f < numFields; ++f) { 1846 PetscInt fdof, fcdof, fc, f2, poff = 0; 1847 1848 /* Can get rid of this loop by storing field information in the global section */ 1849 for (f2 = 0; f2 < fields[f]; ++f2) { 1850 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1851 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1852 poff += fdof-fcdof; 1853 } 1854 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1855 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1856 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1857 subIndices[subOff] = goff+poff+fc; 1858 } 1859 } 1860 } 1861 } 1862 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1863 if (subdm) { 1864 PetscSection subsection; 1865 PetscBool haveNull = PETSC_FALSE; 1866 PetscInt f, nf = 0; 1867 1868 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1869 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1870 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1871 for (f = 0; f < numFields; ++f) { 1872 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1873 if ((*subdm)->nullspaceConstructors[f]) { 1874 haveNull = PETSC_TRUE; 1875 nf = f; 1876 } 1877 } 1878 if (haveNull) { 1879 MatNullSpace nullSpace; 1880 1881 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1882 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1883 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1884 } 1885 if (dm->fields) { 1886 if (nF != dm->numFields) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1887 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1888 for (f = 0; f < numFields; ++f) { 1889 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1890 } 1891 if (numFields == 1) { 1892 MatNullSpace space; 1893 Mat pmat; 1894 1895 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject *) &space);CHKERRQ(ierr); 1896 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1897 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject *) &space);CHKERRQ(ierr); 1898 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1899 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject *) &pmat);CHKERRQ(ierr); 1900 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1901 } 1902 } 1903 } 1904 PetscFunctionReturn(0); 1905 } 1906 1907 #undef __FUNCT__ 1908 #define __FUNCT__ "DMPlexSymmetrize" 1909 /*@ 1910 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1911 1912 Not collective 1913 1914 Input Parameter: 1915 . mesh - The DMPlex 1916 1917 Output Parameter: 1918 1919 Note: 1920 This should be called after all calls to DMPlexSetCone() 1921 1922 Level: beginner 1923 1924 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1925 @*/ 1926 PetscErrorCode DMPlexSymmetrize(DM dm) 1927 { 1928 DM_Plex *mesh = (DM_Plex *) dm->data; 1929 PetscInt *offsets; 1930 PetscInt supportSize; 1931 PetscInt pStart, pEnd, p; 1932 PetscErrorCode ierr; 1933 1934 PetscFunctionBegin; 1935 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1936 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1937 /* Calculate support sizes */ 1938 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1939 for (p = pStart; p < pEnd; ++p) { 1940 PetscInt dof, off, c; 1941 1942 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1943 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1944 for (c = off; c < off+dof; ++c) { 1945 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1946 } 1947 } 1948 for (p = pStart; p < pEnd; ++p) { 1949 PetscInt dof; 1950 1951 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1952 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1953 } 1954 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1955 /* Calculate supports */ 1956 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1957 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1958 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1959 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1960 for (p = pStart; p < pEnd; ++p) { 1961 PetscInt dof, off, c; 1962 1963 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1964 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1965 for (c = off; c < off+dof; ++c) { 1966 const PetscInt q = mesh->cones[c]; 1967 PetscInt offS; 1968 1969 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1970 mesh->supports[offS+offsets[q]] = p; 1971 ++offsets[q]; 1972 } 1973 } 1974 ierr = PetscFree(offsets);CHKERRQ(ierr); 1975 PetscFunctionReturn(0); 1976 } 1977 1978 #undef __FUNCT__ 1979 #define __FUNCT__ "DMPlexSetDepth_Private" 1980 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1981 { 1982 PetscInt d; 1983 PetscErrorCode ierr; 1984 1985 PetscFunctionBegin; 1986 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1987 if (d < 0) { 1988 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1989 const PetscInt *cone = PETSC_NULL; 1990 PetscInt dCone; 1991 1992 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1993 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1994 d = dCone+1; 1995 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1996 } 1997 *depth = d; 1998 PetscFunctionReturn(0); 1999 } 2000 2001 #undef __FUNCT__ 2002 #define __FUNCT__ "DMPlexStratify" 2003 /*@ 2004 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2005 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2006 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2007 the DAG. 2008 2009 Not collective 2010 2011 Input Parameter: 2012 . mesh - The DMPlex 2013 2014 Output Parameter: 2015 2016 Notes: 2017 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2018 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2019 2020 This should be called after all calls to DMPlexSymmetrize() 2021 2022 Level: beginner 2023 2024 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2025 @*/ 2026 PetscErrorCode DMPlexStratify(DM dm) 2027 { 2028 DM_Plex *mesh = (DM_Plex *) dm->data; 2029 PetscInt pStart, pEnd, p; 2030 PetscInt numRoots = 0, numLeaves = 0; 2031 PetscErrorCode ierr; 2032 2033 PetscFunctionBegin; 2034 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2035 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2036 /* Calculate depth */ 2037 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2038 /* Initialize roots and count leaves */ 2039 for (p = pStart; p < pEnd; ++p) { 2040 PetscInt coneSize, supportSize; 2041 2042 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2043 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2044 if (!coneSize && supportSize) { 2045 ++numRoots; 2046 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2047 } else if (!supportSize && coneSize) { 2048 ++numLeaves; 2049 } else if (!supportSize && !coneSize) { 2050 /* Isolated points */ 2051 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2052 } 2053 } 2054 if (numRoots + numLeaves == (pEnd - pStart)) { 2055 for (p = pStart; p < pEnd; ++p) { 2056 PetscInt coneSize, supportSize; 2057 2058 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2059 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2060 if (!supportSize && coneSize) { 2061 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2062 } 2063 } 2064 } else { 2065 /* This might be slow since lookup is not fast */ 2066 for (p = pStart; p < pEnd; ++p) { 2067 PetscInt depth; 2068 2069 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2070 } 2071 } 2072 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2073 PetscFunctionReturn(0); 2074 } 2075 2076 #undef __FUNCT__ 2077 #define __FUNCT__ "DMPlexGetJoin" 2078 /*@C 2079 DMPlexGetJoin - Get an array for the join of the set of points 2080 2081 Not Collective 2082 2083 Input Parameters: 2084 + dm - The DMPlex object 2085 . numPoints - The number of input points for the join 2086 - points - The input points 2087 2088 Output Parameters: 2089 + numCoveredPoints - The number of points in the join 2090 - coveredPoints - The points in the join 2091 2092 Level: intermediate 2093 2094 Note: Currently, this is restricted to a single level join 2095 2096 .keywords: mesh 2097 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2098 @*/ 2099 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2100 { 2101 DM_Plex *mesh = (DM_Plex *) dm->data; 2102 PetscInt *join[2]; 2103 PetscInt joinSize, i = 0; 2104 PetscInt dof, off, p, c, m; 2105 PetscErrorCode ierr; 2106 2107 PetscFunctionBegin; 2108 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2109 PetscValidPointer(points, 2); 2110 PetscValidPointer(numCoveredPoints, 3); 2111 PetscValidPointer(coveredPoints, 4); 2112 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2113 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2114 /* Copy in support of first point */ 2115 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2116 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2117 for (joinSize = 0; joinSize < dof; ++joinSize) { 2118 join[i][joinSize] = mesh->supports[off+joinSize]; 2119 } 2120 /* Check each successive support */ 2121 for (p = 1; p < numPoints; ++p) { 2122 PetscInt newJoinSize = 0; 2123 2124 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2125 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2126 for (c = 0; c < dof; ++c) { 2127 const PetscInt point = mesh->supports[off+c]; 2128 2129 for (m = 0; m < joinSize; ++m) { 2130 if (point == join[i][m]) { 2131 join[1-i][newJoinSize++] = point; 2132 break; 2133 } 2134 } 2135 } 2136 joinSize = newJoinSize; 2137 i = 1-i; 2138 } 2139 *numCoveredPoints = joinSize; 2140 *coveredPoints = join[i]; 2141 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2142 PetscFunctionReturn(0); 2143 } 2144 2145 #undef __FUNCT__ 2146 #define __FUNCT__ "DMPlexRestoreJoin" 2147 /*@C 2148 DMPlexRestoreJoin - Restore an array for the join of the set of points 2149 2150 Not Collective 2151 2152 Input Parameters: 2153 + dm - The DMPlex object 2154 . numPoints - The number of input points for the join 2155 - points - The input points 2156 2157 Output Parameters: 2158 + numCoveredPoints - The number of points in the join 2159 - coveredPoints - The points in the join 2160 2161 Level: intermediate 2162 2163 .keywords: mesh 2164 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2165 @*/ 2166 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2167 { 2168 PetscErrorCode ierr; 2169 2170 PetscFunctionBegin; 2171 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2172 PetscValidPointer(coveredPoints, 4); 2173 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2174 PetscFunctionReturn(0); 2175 } 2176 2177 #undef __FUNCT__ 2178 #define __FUNCT__ "DMPlexGetFullJoin" 2179 /*@C 2180 DMPlexGetFullJoin - Get an array for the join of the set of points 2181 2182 Not Collective 2183 2184 Input Parameters: 2185 + dm - The DMPlex object 2186 . numPoints - The number of input points for the join 2187 - points - The input points 2188 2189 Output Parameters: 2190 + numCoveredPoints - The number of points in the join 2191 - coveredPoints - The points in the join 2192 2193 Level: intermediate 2194 2195 .keywords: mesh 2196 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2197 @*/ 2198 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2199 { 2200 DM_Plex *mesh = (DM_Plex *) dm->data; 2201 PetscInt *offsets, **closures; 2202 PetscInt *join[2]; 2203 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2204 PetscInt p, d, c, m; 2205 PetscErrorCode ierr; 2206 2207 PetscFunctionBegin; 2208 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2209 PetscValidPointer(points, 2); 2210 PetscValidPointer(numCoveredPoints, 3); 2211 PetscValidPointer(coveredPoints, 4); 2212 2213 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2214 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2215 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2216 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2217 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2218 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2219 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2220 2221 for (p = 0; p < numPoints; ++p) { 2222 PetscInt closureSize; 2223 2224 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2225 offsets[p*(depth+2)+0] = 0; 2226 for (d = 0; d < depth+1; ++d) { 2227 PetscInt pStart, pEnd, i; 2228 2229 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2230 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2231 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2232 offsets[p*(depth+2)+d+1] = i; 2233 break; 2234 } 2235 } 2236 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2237 } 2238 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2239 } 2240 for (d = 0; d < depth+1; ++d) { 2241 PetscInt dof; 2242 2243 /* Copy in support of first point */ 2244 dof = offsets[d+1] - offsets[d]; 2245 for (joinSize = 0; joinSize < dof; ++joinSize) { 2246 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2247 } 2248 /* Check each successive cone */ 2249 for (p = 1; p < numPoints && joinSize; ++p) { 2250 PetscInt newJoinSize = 0; 2251 2252 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2253 for (c = 0; c < dof; ++c) { 2254 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2255 2256 for (m = 0; m < joinSize; ++m) { 2257 if (point == join[i][m]) { 2258 join[1-i][newJoinSize++] = point; 2259 break; 2260 } 2261 } 2262 } 2263 joinSize = newJoinSize; 2264 i = 1-i; 2265 } 2266 if (joinSize) break; 2267 } 2268 *numCoveredPoints = joinSize; 2269 *coveredPoints = join[i]; 2270 for (p = 0; p < numPoints; ++p) { 2271 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2272 } 2273 ierr = PetscFree(closures);CHKERRQ(ierr); 2274 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2275 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2276 PetscFunctionReturn(0); 2277 } 2278 2279 #undef __FUNCT__ 2280 #define __FUNCT__ "DMPlexGetMeet" 2281 /*@C 2282 DMPlexGetMeet - Get an array for the meet of the set of points 2283 2284 Not Collective 2285 2286 Input Parameters: 2287 + dm - The DMPlex object 2288 . numPoints - The number of input points for the meet 2289 - points - The input points 2290 2291 Output Parameters: 2292 + numCoveredPoints - The number of points in the meet 2293 - coveredPoints - The points in the meet 2294 2295 Level: intermediate 2296 2297 Note: Currently, this is restricted to a single level meet 2298 2299 .keywords: mesh 2300 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2301 @*/ 2302 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2303 { 2304 DM_Plex *mesh = (DM_Plex *) dm->data; 2305 PetscInt *meet[2]; 2306 PetscInt meetSize, i = 0; 2307 PetscInt dof, off, p, c, m; 2308 PetscErrorCode ierr; 2309 2310 PetscFunctionBegin; 2311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2312 PetscValidPointer(points, 2); 2313 PetscValidPointer(numCoveringPoints, 3); 2314 PetscValidPointer(coveringPoints, 4); 2315 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2316 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2317 /* Copy in cone of first point */ 2318 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2319 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2320 for (meetSize = 0; meetSize < dof; ++meetSize) { 2321 meet[i][meetSize] = mesh->cones[off+meetSize]; 2322 } 2323 /* Check each successive cone */ 2324 for (p = 1; p < numPoints; ++p) { 2325 PetscInt newMeetSize = 0; 2326 2327 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2328 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2329 for (c = 0; c < dof; ++c) { 2330 const PetscInt point = mesh->cones[off+c]; 2331 2332 for (m = 0; m < meetSize; ++m) { 2333 if (point == meet[i][m]) { 2334 meet[1-i][newMeetSize++] = point; 2335 break; 2336 } 2337 } 2338 } 2339 meetSize = newMeetSize; 2340 i = 1-i; 2341 } 2342 *numCoveringPoints = meetSize; 2343 *coveringPoints = meet[i]; 2344 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2345 PetscFunctionReturn(0); 2346 } 2347 2348 #undef __FUNCT__ 2349 #define __FUNCT__ "DMPlexRestoreMeet" 2350 /*@C 2351 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2352 2353 Not Collective 2354 2355 Input Parameters: 2356 + dm - The DMPlex object 2357 . numPoints - The number of input points for the meet 2358 - points - The input points 2359 2360 Output Parameters: 2361 + numCoveredPoints - The number of points in the meet 2362 - coveredPoints - The points in the meet 2363 2364 Level: intermediate 2365 2366 .keywords: mesh 2367 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2368 @*/ 2369 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2370 { 2371 PetscErrorCode ierr; 2372 2373 PetscFunctionBegin; 2374 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2375 PetscValidPointer(coveredPoints, 4); 2376 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2377 PetscFunctionReturn(0); 2378 } 2379 2380 #undef __FUNCT__ 2381 #define __FUNCT__ "DMPlexGetFullMeet" 2382 /*@C 2383 DMPlexGetFullMeet - Get an array for the meet of the set of points 2384 2385 Not Collective 2386 2387 Input Parameters: 2388 + dm - The DMPlex object 2389 . numPoints - The number of input points for the meet 2390 - points - The input points 2391 2392 Output Parameters: 2393 + numCoveredPoints - The number of points in the meet 2394 - coveredPoints - The points in the meet 2395 2396 Level: intermediate 2397 2398 .keywords: mesh 2399 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2400 @*/ 2401 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2402 { 2403 DM_Plex *mesh = (DM_Plex *) dm->data; 2404 PetscInt *offsets, **closures; 2405 PetscInt *meet[2]; 2406 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2407 PetscInt p, h, c, m; 2408 PetscErrorCode ierr; 2409 2410 PetscFunctionBegin; 2411 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2412 PetscValidPointer(points, 2); 2413 PetscValidPointer(numCoveredPoints, 3); 2414 PetscValidPointer(coveredPoints, 4); 2415 2416 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2417 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2418 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2419 maxSize = PetscPowInt(mesh->maxConeSize,height); 2420 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2421 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2422 2423 for (p = 0; p < numPoints; ++p) { 2424 PetscInt closureSize; 2425 2426 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2427 offsets[p*(height+2)+0] = 0; 2428 for (h = 0; h < height+1; ++h) { 2429 PetscInt pStart, pEnd, i; 2430 2431 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2432 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2433 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2434 offsets[p*(height+2)+h+1] = i; 2435 break; 2436 } 2437 } 2438 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2439 } 2440 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2441 } 2442 for (h = 0; h < height+1; ++h) { 2443 PetscInt dof; 2444 2445 /* Copy in cone of first point */ 2446 dof = offsets[h+1] - offsets[h]; 2447 for (meetSize = 0; meetSize < dof; ++meetSize) { 2448 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2449 } 2450 /* Check each successive cone */ 2451 for (p = 1; p < numPoints && meetSize; ++p) { 2452 PetscInt newMeetSize = 0; 2453 2454 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2455 for (c = 0; c < dof; ++c) { 2456 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2457 2458 for (m = 0; m < meetSize; ++m) { 2459 if (point == meet[i][m]) { 2460 meet[1-i][newMeetSize++] = point; 2461 break; 2462 } 2463 } 2464 } 2465 meetSize = newMeetSize; 2466 i = 1-i; 2467 } 2468 if (meetSize) break; 2469 } 2470 *numCoveredPoints = meetSize; 2471 *coveredPoints = meet[i]; 2472 for (p = 0; p < numPoints; ++p) { 2473 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2474 } 2475 ierr = PetscFree(closures);CHKERRQ(ierr); 2476 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2477 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2478 PetscFunctionReturn(0); 2479 } 2480 2481 #undef __FUNCT__ 2482 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2483 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2484 { 2485 MPI_Comm comm = ((PetscObject) dm)->comm; 2486 PetscInt cellDim; 2487 PetscErrorCode ierr; 2488 2489 PetscFunctionBegin; 2490 PetscValidPointer(numFaceVertices,3); 2491 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2492 switch (cellDim) { 2493 case 0: 2494 *numFaceVertices = 0; 2495 break; 2496 case 1: 2497 *numFaceVertices = 1; 2498 break; 2499 case 2: 2500 switch (numCorners) { 2501 case 3: /* triangle */ 2502 *numFaceVertices = 2; /* Edge has 2 vertices */ 2503 break; 2504 case 4: /* quadrilateral */ 2505 *numFaceVertices = 2; /* Edge has 2 vertices */ 2506 break; 2507 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2508 *numFaceVertices = 3; /* Edge has 3 vertices */ 2509 break; 2510 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2511 *numFaceVertices = 3; /* Edge has 3 vertices */ 2512 break; 2513 default: 2514 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2515 } 2516 break; 2517 case 3: 2518 switch (numCorners) { 2519 case 4: /* tetradehdron */ 2520 *numFaceVertices = 3; /* Face has 3 vertices */ 2521 break; 2522 case 6: /* tet cohesive cells */ 2523 *numFaceVertices = 4; /* Face has 4 vertices */ 2524 break; 2525 case 8: /* hexahedron */ 2526 *numFaceVertices = 4; /* Face has 4 vertices */ 2527 break; 2528 case 9: /* tet cohesive Lagrange cells */ 2529 *numFaceVertices = 6; /* Face has 6 vertices */ 2530 break; 2531 case 10: /* quadratic tetrahedron */ 2532 *numFaceVertices = 6; /* Face has 6 vertices */ 2533 break; 2534 case 12: /* hex cohesive Lagrange cells */ 2535 *numFaceVertices = 6; /* Face has 6 vertices */ 2536 break; 2537 case 18: /* quadratic tet cohesive Lagrange cells */ 2538 *numFaceVertices = 6; /* Face has 6 vertices */ 2539 break; 2540 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2541 *numFaceVertices = 9; /* Face has 9 vertices */ 2542 break; 2543 default: 2544 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2545 } 2546 break; 2547 default: 2548 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2549 } 2550 PetscFunctionReturn(0); 2551 } 2552 2553 #undef __FUNCT__ 2554 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2555 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2556 { 2557 const PetscInt maxFaceCases = 30; 2558 PetscInt numFaceCases = 0; 2559 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2560 PetscInt *off, *adj; 2561 PetscInt *neighborCells, *tmpClosure; 2562 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2563 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2564 PetscErrorCode ierr; 2565 2566 PetscFunctionBegin; 2567 /* For parallel partitioning, I think you have to communicate supports */ 2568 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2569 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2570 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2571 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2572 if (cEnd - cStart == 0) { 2573 if (numVertices) *numVertices = 0; 2574 if (offsets) *offsets = PETSC_NULL; 2575 if (adjacency) *adjacency = PETSC_NULL; 2576 PetscFunctionReturn(0); 2577 } 2578 numCells = cEnd - cStart; 2579 /* Setup face recognition */ 2580 { 2581 PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */ 2582 2583 for (c = cStart; c < cEnd; ++c) { 2584 PetscInt corners; 2585 2586 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2587 if (!cornersSeen[corners]) { 2588 PetscInt nFV; 2589 2590 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2591 cornersSeen[corners] = 1; 2592 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2593 numFaceVertices[numFaceCases++] = nFV; 2594 } 2595 } 2596 } 2597 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2598 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2599 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2600 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2601 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2602 /* Count neighboring cells */ 2603 for (cell = cStart; cell < cEnd; ++cell) { 2604 PetscInt numNeighbors = maxNeighbors, n; 2605 2606 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2607 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2608 for (n = 0; n < numNeighbors; ++n) { 2609 PetscInt cellPair[2]; 2610 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2611 PetscInt meetSize = 0; 2612 const PetscInt *meet = PETSC_NULL; 2613 2614 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2615 if (cellPair[0] == cellPair[1]) continue; 2616 if (!found) { 2617 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2618 if (meetSize) { 2619 PetscInt f; 2620 2621 for (f = 0; f < numFaceCases; ++f) { 2622 if (numFaceVertices[f] == meetSize) { 2623 found = PETSC_TRUE; 2624 break; 2625 } 2626 } 2627 } 2628 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2629 } 2630 if (found) { 2631 ++off[cell-cStart+1]; 2632 } 2633 } 2634 } 2635 /* Prefix sum */ 2636 for (cell = 1; cell <= numCells; ++cell) { 2637 off[cell] += off[cell-1]; 2638 } 2639 if (adjacency) { 2640 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2641 /* Get neighboring cells */ 2642 for (cell = cStart; cell < cEnd; ++cell) { 2643 PetscInt numNeighbors = maxNeighbors, n; 2644 PetscInt cellOffset = 0; 2645 2646 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2647 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2648 for (n = 0; n < numNeighbors; ++n) { 2649 PetscInt cellPair[2]; 2650 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2651 PetscInt meetSize = 0; 2652 const PetscInt *meet = PETSC_NULL; 2653 2654 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2655 if (cellPair[0] == cellPair[1]) continue; 2656 if (!found) { 2657 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2658 if (meetSize) { 2659 PetscInt f; 2660 2661 for (f = 0; f < numFaceCases; ++f) { 2662 if (numFaceVertices[f] == meetSize) { 2663 found = PETSC_TRUE; 2664 break; 2665 } 2666 } 2667 } 2668 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2669 } 2670 if (found) { 2671 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2672 ++cellOffset; 2673 } 2674 } 2675 } 2676 } 2677 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2678 if (numVertices) *numVertices = numCells; 2679 if (offsets) *offsets = off; 2680 if (adjacency) *adjacency = adj; 2681 PetscFunctionReturn(0); 2682 } 2683 2684 #if defined(PETSC_HAVE_CHACO) 2685 #if defined(PETSC_HAVE_UNISTD_H) 2686 #include <unistd.h> 2687 #endif 2688 /* Chaco does not have an include file */ 2689 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2690 float *ewgts, float *x, float *y, float *z, char *outassignname, 2691 char *outfilename, short *assignment, int architecture, int ndims_tot, 2692 int mesh_dims[3], double *goal, int global_method, int local_method, 2693 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2694 2695 extern int FREE_GRAPH; 2696 2697 #undef __FUNCT__ 2698 #define __FUNCT__ "DMPlexPartition_Chaco" 2699 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2700 { 2701 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2702 MPI_Comm comm = ((PetscObject) dm)->comm; 2703 int nvtxs = numVertices; /* number of vertices in full graph */ 2704 int *vwgts = NULL; /* weights for all vertices */ 2705 float *ewgts = NULL; /* weights for all edges */ 2706 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2707 char *outassignname = NULL; /* name of assignment output file */ 2708 char *outfilename = NULL; /* output file name */ 2709 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2710 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2711 int mesh_dims[3]; /* dimensions of mesh of processors */ 2712 double *goal = NULL; /* desired set sizes for each set */ 2713 int global_method = 1; /* global partitioning algorithm */ 2714 int local_method = 1; /* local partitioning algorithm */ 2715 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2716 int vmax = 200; /* how many vertices to coarsen down to? */ 2717 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2718 double eigtol = 0.001; /* tolerance on eigenvectors */ 2719 long seed = 123636512; /* for random graph mutations */ 2720 short int *assignment; /* Output partition */ 2721 int fd_stdout, fd_pipe[2]; 2722 PetscInt *points; 2723 PetscMPIInt commSize; 2724 int i, v, p; 2725 PetscErrorCode ierr; 2726 2727 PetscFunctionBegin; 2728 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2729 if (!numVertices) { 2730 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2731 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2732 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2733 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2734 PetscFunctionReturn(0); 2735 } 2736 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2737 for (i = 0; i < start[numVertices]; ++i) { 2738 ++adjacency[i]; 2739 } 2740 if (global_method == INERTIAL_METHOD) { 2741 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2742 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2743 } 2744 mesh_dims[0] = commSize; 2745 mesh_dims[1] = 1; 2746 mesh_dims[2] = 1; 2747 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2748 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2749 /* TODO: check error codes for UNIX calls */ 2750 #if defined(PETSC_HAVE_UNISTD_H) 2751 { 2752 int piperet; 2753 piperet = pipe(fd_pipe); 2754 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2755 fd_stdout = dup(1); 2756 close(1); 2757 dup2(fd_pipe[1], 1); 2758 } 2759 #endif 2760 ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2761 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2762 vmax, ndims, eigtol, seed); 2763 #if defined(PETSC_HAVE_UNISTD_H) 2764 { 2765 char msgLog[10000]; 2766 int count; 2767 2768 fflush(stdout); 2769 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2770 if (count < 0) count = 0; 2771 msgLog[count] = 0; 2772 close(1); 2773 dup2(fd_stdout, 1); 2774 close(fd_stdout); 2775 close(fd_pipe[0]); 2776 close(fd_pipe[1]); 2777 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2778 } 2779 #endif 2780 /* Convert to PetscSection+IS */ 2781 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2782 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2783 for (v = 0; v < nvtxs; ++v) { 2784 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2785 } 2786 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2787 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2788 for (p = 0, i = 0; p < commSize; ++p) { 2789 for (v = 0; v < nvtxs; ++v) { 2790 if (assignment[v] == p) points[i++] = v; 2791 } 2792 } 2793 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2794 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2795 if (global_method == INERTIAL_METHOD) { 2796 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2797 } 2798 ierr = PetscFree(assignment);CHKERRQ(ierr); 2799 for (i = 0; i < start[numVertices]; ++i) { 2800 --adjacency[i]; 2801 } 2802 PetscFunctionReturn(0); 2803 } 2804 #endif 2805 2806 #if defined(PETSC_HAVE_PARMETIS) 2807 #undef __FUNCT__ 2808 #define __FUNCT__ "DMPlexPartition_ParMetis" 2809 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2810 { 2811 PetscFunctionBegin; 2812 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2813 PetscFunctionReturn(0); 2814 } 2815 #endif 2816 2817 #undef __FUNCT__ 2818 #define __FUNCT__ "DMPlexEnlargePartition" 2819 /* Expand the partition by BFS on the adjacency graph */ 2820 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2821 { 2822 PetscHashI h; 2823 const PetscInt *points; 2824 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2825 PetscInt pStart, pEnd, part, q; 2826 PetscErrorCode ierr; 2827 2828 PetscFunctionBegin; 2829 PetscHashICreate(h); 2830 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2831 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2832 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2833 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2834 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2835 for (part = pStart; part < pEnd; ++part) { 2836 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2837 2838 PetscHashIClear(h); 2839 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2840 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2841 /* Add all existing points to h */ 2842 for (p = 0; p < numPoints; ++p) { 2843 const PetscInt point = points[off+p]; 2844 PetscHashIAdd(h, point, 1); 2845 } 2846 PetscHashISize(h, nP); 2847 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2848 /* Add all points in next BFS level */ 2849 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2850 for (p = 0; p < numPoints; ++p) { 2851 const PetscInt point = points[off+p]; 2852 PetscInt s = start[point], e = start[point+1], a; 2853 2854 for (a = s; a < e; ++a) { 2855 PetscHashIAdd(h, adjacency[a], 1); 2856 } 2857 } 2858 PetscHashISize(h, numNewPoints); 2859 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2860 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2861 if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2862 totPoints += numNewPoints; 2863 } 2864 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2865 PetscHashIDestroy(h); 2866 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2867 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2868 for (part = pStart, q = 0; part < pEnd; ++part) { 2869 PetscInt numPoints, p; 2870 2871 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2872 for (p = 0; p < numPoints; ++p, ++q) { 2873 newPoints[q] = tmpPoints[part][p]; 2874 } 2875 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2876 } 2877 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2878 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2879 PetscFunctionReturn(0); 2880 } 2881 2882 #undef __FUNCT__ 2883 #define __FUNCT__ "DMPlexCreatePartition" 2884 /* 2885 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2886 2887 Collective on DM 2888 2889 Input Parameters: 2890 + dm - The DM 2891 . height - The height for points in the partition 2892 - enlarge - Expand each partition with neighbors 2893 2894 Output Parameters: 2895 + partSection - The PetscSection giving the division of points by partition 2896 . partition - The list of points by partition 2897 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2898 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2899 2900 Level: developer 2901 2902 .seealso DMPlexDistribute() 2903 */ 2904 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2905 { 2906 PetscMPIInt size; 2907 PetscErrorCode ierr; 2908 2909 PetscFunctionBegin; 2910 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2911 *origPartSection = PETSC_NULL; 2912 *origPartition = PETSC_NULL; 2913 if (size == 1) { 2914 PetscInt *points; 2915 PetscInt cStart, cEnd, c; 2916 2917 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2918 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2919 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2920 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2921 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2922 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2923 for (c = cStart; c < cEnd; ++c) { 2924 points[c] = c; 2925 } 2926 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2927 PetscFunctionReturn(0); 2928 } 2929 if (height == 0) { 2930 PetscInt numVertices; 2931 PetscInt *start = PETSC_NULL; 2932 PetscInt *adjacency = PETSC_NULL; 2933 2934 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2935 if (1) { 2936 #if defined(PETSC_HAVE_CHACO) 2937 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2938 #endif 2939 } else { 2940 #if defined(PETSC_HAVE_PARMETIS) 2941 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2942 #endif 2943 } 2944 if (enlarge) { 2945 *origPartSection = *partSection; 2946 *origPartition = *partition; 2947 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2948 } 2949 ierr = PetscFree(start);CHKERRQ(ierr); 2950 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2951 # if 0 2952 } else if (height == 1) { 2953 /* Build the dual graph for faces and partition the hypergraph */ 2954 PetscInt numEdges; 2955 2956 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2957 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2958 destroyCSR(numEdges, start, adjacency); 2959 #endif 2960 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2961 PetscFunctionReturn(0); 2962 } 2963 2964 #undef __FUNCT__ 2965 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2966 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2967 { 2968 /* const PetscInt height = 0; */ 2969 const PetscInt *partArray; 2970 PetscInt *allPoints, *partPoints = PETSC_NULL; 2971 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2972 PetscErrorCode ierr; 2973 2974 PetscFunctionBegin; 2975 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2976 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2977 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2978 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2979 for (rank = rStart; rank < rEnd; ++rank) { 2980 PetscInt partSize = 0; 2981 PetscInt numPoints, offset, p; 2982 2983 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2984 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2985 for (p = 0; p < numPoints; ++p) { 2986 PetscInt point = partArray[offset+p], closureSize, c; 2987 PetscInt *closure = PETSC_NULL; 2988 2989 /* TODO Include support for height > 0 case */ 2990 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2991 /* Merge into existing points */ 2992 if (partSize+closureSize > maxPartSize) { 2993 PetscInt *tmpPoints; 2994 2995 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2996 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2997 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2998 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2999 partPoints = tmpPoints; 3000 } 3001 for (c = 0; c < closureSize; ++c) { 3002 partPoints[partSize+c] = closure[c*2]; 3003 } 3004 partSize += closureSize; 3005 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3006 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3007 } 3008 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3009 } 3010 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3011 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3012 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3013 3014 for (rank = rStart; rank < rEnd; ++rank) { 3015 PetscInt partSize = 0, newOffset; 3016 PetscInt numPoints, offset, p; 3017 3018 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3019 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3020 for (p = 0; p < numPoints; ++p) { 3021 PetscInt point = partArray[offset+p], closureSize, c; 3022 PetscInt *closure = PETSC_NULL; 3023 3024 /* TODO Include support for height > 0 case */ 3025 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3026 /* Merge into existing points */ 3027 for (c = 0; c < closureSize; ++c) { 3028 partPoints[partSize+c] = closure[c*2]; 3029 } 3030 partSize += closureSize; 3031 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3032 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3033 } 3034 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3035 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3036 } 3037 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3038 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3039 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3040 PetscFunctionReturn(0); 3041 } 3042 3043 #undef __FUNCT__ 3044 #define __FUNCT__ "DMPlexDistributeField" 3045 /* 3046 Input Parameters: 3047 . originalSection 3048 , originalVec 3049 3050 Output Parameters: 3051 . newSection 3052 . newVec 3053 */ 3054 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3055 { 3056 PetscSF fieldSF; 3057 PetscInt *remoteOffsets, fieldSize; 3058 PetscScalar *originalValues, *newValues; 3059 PetscErrorCode ierr; 3060 3061 PetscFunctionBegin; 3062 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3063 3064 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3065 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3066 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3067 3068 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3069 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3070 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3071 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3072 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3073 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3074 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3075 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3076 PetscFunctionReturn(0); 3077 } 3078 3079 #undef __FUNCT__ 3080 #define __FUNCT__ "DMPlexDistribute" 3081 /*@C 3082 DMPlexDistribute - Distributes the mesh and any associated sections. 3083 3084 Not Collective 3085 3086 Input Parameter: 3087 + dm - The original DMPlex object 3088 . partitioner - The partitioning package, or NULL for the default 3089 - overlap - The overlap of partitions, 0 is the default 3090 3091 Output Parameter: 3092 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3093 3094 Note: If the mesh was not distributed, the return value is PETSC_NULL 3095 3096 Level: intermediate 3097 3098 .keywords: mesh, elements 3099 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3100 @*/ 3101 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3102 { 3103 DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3104 MPI_Comm comm = ((PetscObject) dm)->comm; 3105 const PetscInt height = 0; 3106 PetscInt dim, numRemoteRanks; 3107 IS origCellPart, cellPart, part; 3108 PetscSection origCellPartSection, cellPartSection, partSection; 3109 PetscSFNode *remoteRanks; 3110 PetscSF partSF, pointSF, coneSF; 3111 ISLocalToGlobalMapping renumbering; 3112 PetscSection originalConeSection, newConeSection; 3113 PetscInt *remoteOffsets; 3114 PetscInt *cones, *newCones, newConesSize; 3115 PetscBool flg; 3116 PetscMPIInt rank, numProcs, p; 3117 PetscErrorCode ierr; 3118 3119 PetscFunctionBegin; 3120 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3121 PetscValidPointer(dmParallel,4); 3122 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3123 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3124 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3125 *dmParallel = PETSC_NULL; 3126 if (numProcs == 1) PetscFunctionReturn(0); 3127 3128 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3129 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3130 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3131 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3132 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3133 if (!rank) { 3134 numRemoteRanks = numProcs; 3135 } else { 3136 numRemoteRanks = 0; 3137 } 3138 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3139 for (p = 0; p < numRemoteRanks; ++p) { 3140 remoteRanks[p].rank = p; 3141 remoteRanks[p].index = 0; 3142 } 3143 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3144 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3145 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3146 if (flg) { 3147 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3148 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3149 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3150 if (origCellPart) { 3151 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3152 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3153 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3154 } 3155 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3156 } 3157 /* Close the partition over the mesh */ 3158 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3159 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3160 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3161 /* Create new mesh */ 3162 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3163 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3164 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3165 pmesh = (DM_Plex *) (*dmParallel)->data; 3166 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3167 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3168 if (flg) { 3169 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3170 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3171 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3172 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3173 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3174 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3175 } 3176 /* Distribute cone section */ 3177 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3178 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3179 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3180 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3181 { 3182 PetscInt pStart, pEnd, p; 3183 3184 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3185 for (p = pStart; p < pEnd; ++p) { 3186 PetscInt coneSize; 3187 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3188 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3189 } 3190 } 3191 /* Communicate and renumber cones */ 3192 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3193 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3194 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3195 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3196 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3197 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3198 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3199 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3200 if (flg) { 3201 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3202 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3203 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3204 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3205 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3206 } 3207 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3208 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3209 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3210 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3211 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3212 /* Create supports and stratify sieve */ 3213 { 3214 PetscInt pStart, pEnd; 3215 3216 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3217 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3218 } 3219 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3220 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3221 /* Distribute Coordinates */ 3222 { 3223 PetscSection originalCoordSection, newCoordSection; 3224 Vec originalCoordinates, newCoordinates; 3225 const char *name; 3226 3227 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3228 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3229 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3230 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3231 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3232 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3233 3234 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3235 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3236 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3237 } 3238 /* Distribute labels */ 3239 { 3240 DMLabel next = mesh->labels, newNext = pmesh->labels; 3241 PetscInt numLabels = 0, l; 3242 3243 /* Bcast number of labels */ 3244 while (next) {++numLabels; next = next->next;} 3245 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3246 next = mesh->labels; 3247 for (l = 0; l < numLabels; ++l) { 3248 DMLabel newLabel; 3249 const PetscInt *partArray; 3250 char *name; 3251 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3252 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3253 PetscInt nameSize, s, p; 3254 PetscBool isdepth; 3255 size_t len = 0; 3256 3257 /* Bcast name (could filter for no points) */ 3258 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3259 nameSize = len; 3260 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3261 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3262 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3263 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3264 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3265 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3266 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3267 newLabel->name = name; 3268 /* Bcast numStrata (could filter for no points in stratum) */ 3269 if (!rank) {newLabel->numStrata = next->numStrata;} 3270 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3271 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3272 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3273 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3274 /* Bcast stratumValues (could filter for no points in stratum) */ 3275 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3276 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3277 /* Find size on each process and Scatter */ 3278 if (!rank) { 3279 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3280 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3281 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3282 for (s = 0; s < next->numStrata; ++s) { 3283 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3284 const PetscInt point = next->points[p]; 3285 PetscInt proc; 3286 3287 for (proc = 0; proc < numProcs; ++proc) { 3288 PetscInt dof, off, pPart; 3289 3290 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3291 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3292 for (pPart = off; pPart < off+dof; ++pPart) { 3293 if (partArray[pPart] == point) { 3294 ++stratumSizes[proc*next->numStrata+s]; 3295 break; 3296 } 3297 } 3298 } 3299 } 3300 } 3301 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3302 } 3303 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3304 /* Calculate stratumOffsets */ 3305 newLabel->stratumOffsets[0] = 0; 3306 for (s = 0; s < newLabel->numStrata; ++s) { 3307 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3308 } 3309 /* Pack points and Scatter */ 3310 if (!rank) { 3311 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3312 displs[0] = 0; 3313 for (p = 0; p < numProcs; ++p) { 3314 sendcnts[p] = 0; 3315 for (s = 0; s < next->numStrata; ++s) { 3316 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3317 } 3318 offsets[p] = displs[p]; 3319 displs[p+1] = displs[p] + sendcnts[p]; 3320 } 3321 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3322 for (s = 0; s < next->numStrata; ++s) { 3323 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3324 const PetscInt point = next->points[p]; 3325 PetscInt proc; 3326 3327 for (proc = 0; proc < numProcs; ++proc) { 3328 PetscInt dof, off, pPart; 3329 3330 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3331 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3332 for (pPart = off; pPart < off+dof; ++pPart) { 3333 if (partArray[pPart] == point) { 3334 points[offsets[proc]++] = point; 3335 break; 3336 } 3337 } 3338 } 3339 } 3340 } 3341 } 3342 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3343 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3344 ierr = PetscFree(points);CHKERRQ(ierr); 3345 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3346 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3347 /* Renumber points */ 3348 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3349 /* Sort points */ 3350 for (s = 0; s < newLabel->numStrata; ++s) { 3351 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3352 } 3353 /* Insert into list */ 3354 if (newNext) { 3355 newNext->next = newLabel; 3356 } else { 3357 pmesh->labels = newLabel; 3358 } 3359 newNext = newLabel; 3360 if (!rank) {next = next->next;} 3361 } 3362 } 3363 /* Cleanup Partition */ 3364 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3365 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3366 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3367 ierr = ISDestroy(&part);CHKERRQ(ierr); 3368 /* Create point SF for parallel mesh */ 3369 { 3370 const PetscInt *leaves; 3371 PetscSFNode *remotePoints, *rowners, *lowners; 3372 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3373 PetscInt pStart, pEnd; 3374 3375 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3376 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3377 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3378 for (p=0; p<numRoots; p++) { 3379 rowners[p].rank = -1; 3380 rowners[p].index = -1; 3381 } 3382 if (origCellPart) { 3383 /* Make sure cells in the original partition are not assigned to other procs */ 3384 const PetscInt *origCells; 3385 3386 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3387 for (p = 0; p < numProcs; ++p) { 3388 PetscInt dof, off, d; 3389 3390 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3391 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3392 for (d = off; d < off+dof; ++d) { 3393 rowners[origCells[d]].rank = p; 3394 } 3395 } 3396 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3397 } 3398 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3399 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3400 3401 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3402 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3403 for (p = 0; p < numLeaves; ++p) { 3404 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3405 lowners[p].rank = rank; 3406 lowners[p].index = leaves ? leaves[p] : p; 3407 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3408 lowners[p].rank = -2; 3409 lowners[p].index = -2; 3410 } 3411 } 3412 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3413 rowners[p].rank = -3; 3414 rowners[p].index = -3; 3415 } 3416 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3417 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3418 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3419 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3420 for (p = 0; p < numLeaves; ++p) { 3421 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3422 if (lowners[p].rank != rank) ++numGhostPoints; 3423 } 3424 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3425 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3426 for (p = 0, gp = 0; p < numLeaves; ++p) { 3427 if (lowners[p].rank != rank) { 3428 ghostPoints[gp] = leaves ? leaves[p] : p; 3429 remotePoints[gp].rank = lowners[p].rank; 3430 remotePoints[gp].index = lowners[p].index; 3431 ++gp; 3432 } 3433 } 3434 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3435 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3436 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3437 } 3438 /* Cleanup */ 3439 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3440 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3441 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3442 PetscFunctionReturn(0); 3443 } 3444 3445 #undef __FUNCT__ 3446 #define __FUNCT__ "DMPlexRenumber_Private" 3447 /* 3448 Reasons to renumber: 3449 3450 1) Permute points, e.g. bandwidth reduction (Renumber) 3451 3452 a) Must not mix strata 3453 3454 2) Shift numbers for point insertion (Shift) 3455 3456 a) Want operation brken into parts so that insertion can be interleaved 3457 3458 renumbering - An IS which provides the new numbering 3459 */ 3460 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3461 { 3462 PetscFunctionBegin; 3463 PetscFunctionReturn(0); 3464 } 3465 3466 #undef __FUNCT__ 3467 #define __FUNCT__ "DMPlexShiftPoint_Private" 3468 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3469 { 3470 if (depth < 0) return p; 3471 /* Cells */ if (p < depthEnd[depth]) return p; 3472 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3473 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3474 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3475 } 3476 3477 #undef __FUNCT__ 3478 #define __FUNCT__ "DMPlexShiftSizes_Private" 3479 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3480 { 3481 PetscInt *depthEnd; 3482 PetscInt depth = 0, d, pStart, pEnd, p; 3483 PetscErrorCode ierr; 3484 3485 PetscFunctionBegin; 3486 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3487 if (depth < 0) PetscFunctionReturn(0); 3488 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3489 /* Step 1: Expand chart */ 3490 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3491 for (d = 0; d <= depth; ++d) { 3492 pEnd += depthShift[d]; 3493 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3494 } 3495 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3496 /* Step 2: Set cone and support sizes */ 3497 for (d = 0; d <= depth; ++d) { 3498 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3499 for (p = pStart; p < pEnd; ++p) { 3500 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3501 PetscInt size; 3502 3503 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3504 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3505 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3506 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3507 } 3508 } 3509 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3510 PetscFunctionReturn(0); 3511 } 3512 3513 #undef __FUNCT__ 3514 #define __FUNCT__ "DMPlexShiftPoints_Private" 3515 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3516 { 3517 PetscInt *depthEnd, *newpoints; 3518 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3519 PetscErrorCode ierr; 3520 3521 PetscFunctionBegin; 3522 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3523 if (depth < 0) PetscFunctionReturn(0); 3524 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3525 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3526 for (d = 0; d <= depth; ++d) { 3527 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3528 } 3529 /* Step 5: Set cones and supports */ 3530 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3531 for (p = pStart; p < pEnd; ++p) { 3532 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3533 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3534 3535 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3536 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3537 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3538 for (i = 0; i < size; ++i) { 3539 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3540 } 3541 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3542 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3543 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3544 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3545 for (i = 0; i < size; ++i) { 3546 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3547 } 3548 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3549 } 3550 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3551 PetscFunctionReturn(0); 3552 } 3553 3554 #undef __FUNCT__ 3555 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3556 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3557 { 3558 PetscSection coordSection, newCoordSection; 3559 Vec coordinates, newCoordinates; 3560 PetscScalar *coords, *newCoords; 3561 PetscInt *depthEnd, coordSize; 3562 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3563 PetscErrorCode ierr; 3564 3565 PetscFunctionBegin; 3566 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3567 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3568 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3569 for (d = 0; d <= depth; ++d) { 3570 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3571 } 3572 /* Step 8: Convert coordinates */ 3573 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3574 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3575 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3576 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3577 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3578 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3579 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3580 for (v = vStartNew; v < vEndNew; ++v) { 3581 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3582 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3583 } 3584 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3585 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3586 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3587 ierr = VecCreate(((PetscObject) dm)->comm, &newCoordinates);CHKERRQ(ierr); 3588 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3589 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3590 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3591 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3592 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3593 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3594 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3595 for (v = vStart; v < vEnd; ++v) { 3596 PetscInt dof, off, noff, d; 3597 3598 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3599 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3600 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3601 for (d = 0; d < dof; ++d) { 3602 newCoords[noff+d] = coords[off+d]; 3603 } 3604 } 3605 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3606 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3607 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3608 PetscFunctionReturn(0); 3609 } 3610 3611 #undef __FUNCT__ 3612 #define __FUNCT__ "DMPlexShiftSF_Private" 3613 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3614 { 3615 PetscInt *depthEnd; 3616 PetscInt depth = 0, d; 3617 PetscSF sfPoint, sfPointNew; 3618 const PetscSFNode *remotePoints; 3619 PetscSFNode *gremotePoints; 3620 const PetscInt *localPoints; 3621 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3622 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3623 PetscMPIInt numProcs; 3624 PetscErrorCode ierr; 3625 3626 PetscFunctionBegin; 3627 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3628 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3629 for (d = 0; d <= depth; ++d) { 3630 totShift += depthShift[d]; 3631 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3632 } 3633 /* Step 9: Convert pointSF */ 3634 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3635 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3636 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3637 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3638 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3639 if (numRoots >= 0) { 3640 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3641 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3642 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3643 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3644 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3645 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3646 for (l = 0; l < numLeaves; ++l) { 3647 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3648 gremotePoints[l].rank = remotePoints[l].rank; 3649 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3650 } 3651 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3652 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3653 } 3654 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3655 PetscFunctionReturn(0); 3656 } 3657 3658 #undef __FUNCT__ 3659 #define __FUNCT__ "DMPlexShiftLabels_Private" 3660 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3661 { 3662 PetscSF sfPoint; 3663 DMLabel vtkLabel, ghostLabel; 3664 PetscInt *depthEnd; 3665 const PetscSFNode *leafRemote; 3666 const PetscInt *leafLocal; 3667 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3668 PetscMPIInt rank; 3669 PetscErrorCode ierr; 3670 3671 PetscFunctionBegin; 3672 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3673 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3674 for (d = 0; d <= depth; ++d) { 3675 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3676 } 3677 /* Step 10: Convert labels */ 3678 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3679 for (l = 0; l < numLabels; ++l) { 3680 DMLabel label, newlabel; 3681 const char *lname; 3682 PetscBool isDepth; 3683 IS valueIS; 3684 const PetscInt *values; 3685 PetscInt numValues, val; 3686 3687 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3688 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3689 if (isDepth) continue; 3690 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3691 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3692 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3693 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3694 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3695 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3696 for (val = 0; val < numValues; ++val) { 3697 IS pointIS; 3698 const PetscInt *points; 3699 PetscInt numPoints, p; 3700 3701 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3702 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3703 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3704 for (p = 0; p < numPoints; ++p) { 3705 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3706 3707 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3708 } 3709 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3710 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3711 } 3712 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3713 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3714 } 3715 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3716 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3717 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3718 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3719 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3720 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3721 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3722 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3723 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3724 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3725 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3726 for (; c < leafLocal[l] && c < cEnd; ++c) { 3727 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3728 } 3729 if (leafLocal[l] >= cEnd) break; 3730 if (leafRemote[l].rank == rank) { 3731 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3732 } else { 3733 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3734 } 3735 } 3736 for (; c < cEnd; ++c) { 3737 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3738 } 3739 if (0) { 3740 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3741 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3742 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3743 } 3744 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3745 for (f = fStart; f < fEnd; ++f) { 3746 PetscInt numCells; 3747 3748 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3749 if (numCells < 2) { 3750 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3751 } else { 3752 const PetscInt *cells = PETSC_NULL; 3753 PetscInt vA, vB; 3754 3755 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3756 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3757 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3758 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3759 } 3760 } 3761 if (0) { 3762 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3763 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3764 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3765 } 3766 PetscFunctionReturn(0); 3767 } 3768 3769 #undef __FUNCT__ 3770 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3771 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3772 { 3773 DMLabel label; 3774 IS valueIS; 3775 const PetscInt *values; 3776 PetscInt *depthShift; 3777 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3778 PetscErrorCode ierr; 3779 3780 PetscFunctionBegin; 3781 /* Count ghost cells */ 3782 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3783 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3784 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3785 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3786 *numGhostCells = 0; 3787 for (fs = 0; fs < numFS; ++fs) { 3788 PetscInt numBdFaces; 3789 3790 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3791 *numGhostCells += numBdFaces; 3792 } 3793 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3794 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3795 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3796 if (depth >= 0) {depthShift[depth] = *numGhostCells;} 3797 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3798 /* Step 3: Set cone/support sizes for new points */ 3799 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3800 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3801 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3802 } 3803 for (fs = 0; fs < numFS; ++fs) { 3804 IS faceIS; 3805 const PetscInt *faces; 3806 PetscInt numFaces, f; 3807 3808 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3809 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3810 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3811 for (f = 0; f < numFaces; ++f) { 3812 PetscInt size; 3813 3814 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3815 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3816 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3817 } 3818 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3819 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3820 } 3821 /* Step 4: Setup ghosted DM */ 3822 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3823 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3824 /* Step 6: Set cones and supports for new points */ 3825 ghostCell = cEnd; 3826 for (fs = 0; fs < numFS; ++fs) { 3827 IS faceIS; 3828 const PetscInt *faces; 3829 PetscInt numFaces, f; 3830 3831 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3832 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3833 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3834 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3835 PetscInt newFace = faces[f] + *numGhostCells; 3836 3837 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3838 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3839 } 3840 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3841 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3842 } 3843 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3844 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3845 /* Step 7: Stratify */ 3846 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3847 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3848 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3849 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3850 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3851 PetscFunctionReturn(0); 3852 } 3853 3854 #undef __FUNCT__ 3855 #define __FUNCT__ "DMPlexConstructGhostCells" 3856 /*@C 3857 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3858 3859 Collective on dm 3860 3861 Input Parameters: 3862 + dm - The original DM 3863 - labelName - The label specifying the boundary faces (this could be auto-generated) 3864 3865 Output Parameters: 3866 + numGhostCells - The number of ghost cells added to the DM 3867 - dmGhosted - The new DM 3868 3869 Level: developer 3870 3871 .seealso: DMCreate() 3872 */ 3873 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3874 { 3875 DM gdm; 3876 PetscInt dim; 3877 PetscErrorCode ierr; 3878 3879 PetscFunctionBegin; 3880 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3881 PetscValidPointer(numGhostCells, 3); 3882 PetscValidPointer(dmGhosted, 4); 3883 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3884 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3885 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3886 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3887 switch (dim) { 3888 case 2: 3889 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3890 break; 3891 default: 3892 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3893 } 3894 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3895 *dmGhosted = gdm; 3896 PetscFunctionReturn(0); 3897 } 3898 3899 #undef __FUNCT__ 3900 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3901 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, const char labelName[], DM sdm) 3902 { 3903 MPI_Comm comm = ((PetscObject) dm)->comm; 3904 DMLabel label; 3905 IS valueIS, *pointIS; 3906 const PetscInt *values, **splitPoints; 3907 PetscSection coordSection; 3908 Vec coordinates; 3909 PetscScalar *coords; 3910 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3911 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3912 PetscErrorCode ierr; 3913 3914 PetscFunctionBegin; 3915 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3916 /* Count split points and add cohesive cells */ 3917 ierr = DMPlexGetLabel(dm, labelName, &label);CHKERRQ(ierr); 3918 if (label) { 3919 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3920 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3921 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3922 } 3923 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3924 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3925 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3926 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3927 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3928 for(d = 0; d <= depth; ++d) { 3929 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &pMaxNew[d]);CHKERRQ(ierr); 3930 numSplitPoints[d] = 0; 3931 splitPoints[d] = PETSC_NULL; 3932 pointIS[d] = PETSC_NULL; 3933 } 3934 for(sp = 0; sp < numSP; ++sp) { 3935 const PetscInt dep = values[sp]; 3936 3937 if ((dep < 0) || (dep > depth)) continue; 3938 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3939 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3940 if (pointIS[dep]) { 3941 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3942 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3943 } 3944 } 3945 if (depth >= 0) { 3946 /* Calculate number of additional points */ 3947 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3948 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3949 /* Calculate hybrid bound for each dimension */ 3950 pMaxNew[0] += depthShift[depth]; 3951 if (depth > 1) {pMaxNew[dim-1] += depthShift[depth] + depthShift[0];} 3952 if (depth > 2) {pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1];} 3953 /* Calculate point offset for each dimension */ 3954 depthOffset[depth] = 0; 3955 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3956 if (depth > 1) {depthOffset[dim-1] = depthOffset[0] + depthShift[0];} 3957 if (depth > 2) {depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1];} 3958 } 3959 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3960 /* Step 3: Set cone/support sizes for new points */ 3961 for(dep = 0; dep <= depth; ++dep) { 3962 for(p = 0; p < numSplitPoints[dep]; ++p) { 3963 const PetscInt oldp = splitPoints[dep][p]; 3964 const PetscInt newp = depthOffset[dep] + oldp; 3965 const PetscInt splitp = pMaxNew[dep] + p; 3966 const PetscInt *support; 3967 PetscInt coneSize, supportSize, q, e; 3968 3969 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3970 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3971 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3972 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3973 if (dep == depth-1) { 3974 const PetscInt ccell = pMaxNew[depth] + p; 3975 /* Add cohesive cells, they are prisms */ 3976 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3977 } else if (dep == 0) { 3978 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3979 3980 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3981 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3982 for(e = 0, q = 0; e < supportSize; ++e) { 3983 PetscInt val; 3984 3985 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3986 if ((val == 1) || (val == (shift + 1))) ++q; 3987 } 3988 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3989 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3990 for(e = 0, q = 0; e < supportSize; ++e) { 3991 PetscInt val; 3992 3993 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3994 if ((val == 1) || (val == -(shift + 1))) ++q; 3995 } 3996 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 3997 /* Add cohesive edges */ 3998 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 3999 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 4000 } else if (dep == dim-2) { 4001 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4002 /* Split old edge: Faces in positive side cells and old split faces */ 4003 for(e = 0, q = 0; e < supportSize; ++e) { 4004 PetscInt val; 4005 4006 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4007 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4008 } 4009 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4010 /* Split new edge: Faces in negative side cells and new split faces */ 4011 for(e = 0, q = 0; e < supportSize; ++e) { 4012 PetscInt val; 4013 4014 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4015 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4016 } 4017 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4018 } 4019 } 4020 } 4021 /* Step 4: Setup split DM */ 4022 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4023 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4024 /* Step 6: Set cones and supports for new points */ 4025 for(dep = 0; dep <= depth; ++dep) { 4026 for(p = 0; p < numSplitPoints[dep]; ++p) { 4027 const PetscInt oldp = splitPoints[dep][p]; 4028 const PetscInt newp = depthOffset[dep] + oldp; 4029 const PetscInt splitp = pMaxNew[dep] + p; 4030 const PetscInt *cone, *support; 4031 PetscInt coneSize, supportSize, q, v, e, s; 4032 4033 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4034 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4035 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4036 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4037 if (dep == depth-1) { 4038 const PetscInt ccell = pMaxNew[depth] + p; 4039 const PetscInt *supportF; 4040 4041 /* Split face: copy in old face to new face to start */ 4042 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4043 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4044 /* Split old face: old vertices/edges in cone so no change */ 4045 /* Split new face: new vertices/edges in cone */ 4046 for(q = 0; q < coneSize; ++q) { 4047 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4048 coneNew[2+q] = pMaxNew[dim-2] + v; 4049 } 4050 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4051 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4052 coneNew[0] = newp; 4053 coneNew[1] = splitp; 4054 for(q = 0; q < coneSize; ++q) { 4055 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4056 } 4057 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4058 4059 4060 for(s = 0; s < supportSize; ++s) { 4061 PetscInt val; 4062 4063 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4064 if (val < 0) { 4065 const PetscInt *scone; 4066 PetscInt sconeSize, sc; 4067 4068 /* Split old face: Replace negative side cell with cohesive cell */ 4069 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4070 } else { 4071 /* Split new face: Replace positive side cell with cohesive cell */ 4072 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4073 } 4074 } 4075 } else if (dep == 0) { 4076 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4077 4078 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4079 for(e = 0, q = 0; e < supportSize; ++e) { 4080 PetscInt val; 4081 4082 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4083 if ((val == 1) || (val == (shift + 1))) { 4084 supportNew[q++] = depthOffset[1] + support[e]; 4085 } 4086 } 4087 supportNew[q] = cedge; 4088 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4089 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4090 for(e = 0, q = 0; e < supportSize; ++e) { 4091 PetscInt val, edge; 4092 4093 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4094 if (val == 1) { 4095 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4096 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4097 supportNew[q++] = pMaxNew[1] + edge; 4098 } else if (val == -(shift + 1)) { 4099 supportNew[q++] = depthOffset[1] + support[e]; 4100 } 4101 } 4102 supportNew[q] = cedge; 4103 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4104 /* Cohesive edge: Old and new split vertex, punting on support */ 4105 coneNew[0] = newp; 4106 coneNew[1] = splitp; 4107 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4108 } else if (dep == dim-2) { 4109 /* Split old edge: old vertices in cone so no change */ 4110 /* Split new edge: new vertices in cone */ 4111 for(q = 0; q < coneSize; ++q) { 4112 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4113 coneNew[q] = pMaxNew[dim-3] + v; 4114 } 4115 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4116 /* Split old edge: Faces in positive side cells and old split faces */ 4117 for(e = 0, q = 0; e < supportSize; ++e) { 4118 PetscInt val; 4119 4120 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4121 if ((val == dim-1) || (val == (shift + dim-1))) { 4122 supportNew[q++] = depthOffset[dim-1] + support[e]; 4123 } 4124 } 4125 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4126 /* Split new edge: Faces in negative side cells and new split faces */ 4127 for(e = 0, q = 0; e < supportSize; ++e) { 4128 PetscInt val, face; 4129 4130 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4131 if (val == dim-1) { 4132 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4133 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4134 supportNew[q++] = pMaxNew[dim-1] + face; 4135 } else if (val == -(shift + dim-1)) { 4136 supportNew[q++] = depthOffset[dim-1] + support[e]; 4137 } 4138 } 4139 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4140 } 4141 } 4142 } 4143 /* Step 6b: Replace split points in negative side cones */ 4144 for(sp = 0; sp < numSP; ++sp) { 4145 PetscInt dep = values[sp]; 4146 IS pIS; 4147 PetscInt numPoints; 4148 const PetscInt *points; 4149 4150 if (dep >= 0) continue; 4151 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4152 if (!pIS) continue; 4153 dep = -dep - shift; 4154 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4155 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4156 for(p = 0; p < numPoints; ++p) { 4157 const PetscInt oldp = points[p]; 4158 const PetscInt newp = depthOffset[dep] + oldp; 4159 const PetscInt splitp = pMaxNew[dep] + p; 4160 const PetscInt *cone; 4161 PetscInt coneSize, c; 4162 PetscBool replaced = PETSC_FALSE; 4163 4164 /* Negative edge: replace split vertex */ 4165 /* Negative cell: replace split face */ 4166 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4167 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4168 for(c = 0; c < coneSize; ++c) { 4169 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4170 PetscInt csplitp, cp, val; 4171 4172 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4173 if (val == dep-1) { 4174 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4175 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4176 csplitp = pMaxNew[dep-1] + cp; 4177 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4178 replaced = PETSC_TRUE; 4179 } 4180 } 4181 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4182 } 4183 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4184 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4185 } 4186 /* Step 7: Stratify */ 4187 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4188 /* Step 8: Coordinates */ 4189 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4190 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4191 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4192 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4193 for(v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4194 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4195 const PetscInt splitp = pMaxNew[0] + v; 4196 PetscInt dof, off, soff, d; 4197 4198 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4199 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4200 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4201 for(d = 0; d < dof; ++d) { 4202 coords[soff+d] = coords[off+d]; 4203 } 4204 } 4205 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4206 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4207 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4208 /* Step 10: Labels */ 4209 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4210 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4211 for (dep = 0; dep <= depth; ++dep) { 4212 for (p = 0; p < numSplitPoints[dep]; ++p) { 4213 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4214 const PetscInt splitp = pMaxNew[dep] + p; 4215 PetscInt l; 4216 4217 for (l = 0; l < numLabels; ++l) { 4218 DMLabel label; 4219 const char *lname; 4220 PetscInt val; 4221 4222 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4223 ierr = DMPlexGetLabel(sdm, lname, &label);CHKERRQ(ierr); 4224 ierr = DMLabelGetValue(label, newp, &val);CHKERRQ(ierr); 4225 if (val >= 0) { 4226 ierr = DMLabelSetValue(label, splitp, val);CHKERRQ(ierr); 4227 if (dep == 0) { 4228 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4229 ierr = DMLabelSetValue(label, cedge, val);CHKERRQ(ierr); 4230 } 4231 } 4232 } 4233 } 4234 } 4235 for (sp = 0; sp < numSP; ++sp) { 4236 const PetscInt dep = values[sp]; 4237 4238 if ((dep < 0) || (dep > depth)) continue; 4239 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4240 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4241 } 4242 if (label) { 4243 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4244 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4245 } 4246 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4247 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4248 PetscFunctionReturn(0); 4249 } 4250 4251 #undef __FUNCT__ 4252 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4253 /*@C 4254 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4255 4256 Collective on dm 4257 4258 Input Parameters: 4259 + dm - The original DM 4260 - labelName - The label specifying the boundary faces (this could be auto-generated) 4261 4262 Output Parameters: 4263 - dmSplit - The new DM 4264 4265 Level: developer 4266 4267 .seealso: DMCreate() 4268 */ 4269 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, const char labelName[], DM *dmSplit) 4270 { 4271 DM sdm; 4272 PetscInt dim; 4273 PetscErrorCode ierr; 4274 4275 PetscFunctionBegin; 4276 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4277 PetscValidPointer(dmSplit, 4); 4278 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4279 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4280 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4281 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4282 switch(dim) { 4283 case 2: 4284 case 3: 4285 ierr = DMPlexConstructCohesiveCells_Private(dm, labelName, sdm);CHKERRQ(ierr); 4286 break; 4287 default: 4288 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4289 } 4290 *dmSplit = sdm; 4291 PetscFunctionReturn(0); 4292 } 4293 4294 #undef __FUNCT__ 4295 #define __FUNCT__ "DMLabelCohesiveComplete" 4296 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4297 { 4298 IS dimIS; 4299 const PetscInt *points; 4300 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4301 PetscErrorCode ierr; 4302 4303 PetscFunctionBegin; 4304 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4305 /* Cell orientation for face gives the side of the fault */ 4306 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4307 if (!dimIS) PetscFunctionReturn(0); 4308 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4309 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4310 for(p = 0; p < numPoints; ++p) { 4311 const PetscInt *support; 4312 PetscInt supportSize, s; 4313 4314 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4315 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4316 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4317 for(s = 0; s < supportSize; ++s) { 4318 const PetscInt *cone, *ornt; 4319 PetscInt coneSize, c; 4320 PetscBool pos = PETSC_TRUE; 4321 4322 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4323 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4324 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4325 for(c = 0; c < coneSize; ++c) { 4326 if (cone[c] == points[p]) { 4327 if (ornt[c] >= 0) { 4328 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4329 } else { 4330 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4331 pos = PETSC_FALSE; 4332 } 4333 break; 4334 } 4335 } 4336 if (c == coneSize) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cell split face %d support does not have it in the cone", points[p]); 4337 /* Put faces touching the fault in the label */ 4338 for(c = 0; c < coneSize; ++c) { 4339 const PetscInt point = cone[c]; 4340 4341 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4342 if (val == -1) { 4343 PetscInt *closure = PETSC_NULL; 4344 PetscInt closureSize, cl; 4345 4346 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4347 for (cl = 0; cl < closureSize*2; cl += 2) { 4348 const PetscInt clp = closure[cl]; 4349 4350 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4351 if ((val >= 0) && (val < dim-1)) { 4352 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4353 break; 4354 } 4355 } 4356 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4357 } 4358 } 4359 } 4360 } 4361 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4362 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4363 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4364 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4365 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4366 if (!dimIS) PetscFunctionReturn(0); 4367 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4368 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4369 for(p = 0; p < numPoints; ++p) { 4370 PetscInt *star = PETSC_NULL; 4371 PetscInt starSize, s; 4372 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4373 4374 /* First mark cells connected to the fault */ 4375 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4376 while (again) { 4377 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4378 again = 0; 4379 for (s = 0; s < starSize*2; s += 2) { 4380 const PetscInt point = star[s]; 4381 const PetscInt *cone; 4382 PetscInt coneSize, c; 4383 4384 if ((point < cStart) || (point >= cEnd)) continue; 4385 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4386 if (val != -1) continue; 4387 again = 2; 4388 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4389 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4390 for(c = 0; c < coneSize; ++c) { 4391 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4392 if (val != -1) { 4393 if (abs(val) < shift) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val); 4394 if (val > 0) { 4395 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4396 } else { 4397 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4398 } 4399 again = 1; 4400 break; 4401 } 4402 } 4403 } 4404 } 4405 /* Classify the rest by cell membership */ 4406 for (s = 0; s < starSize*2; s += 2) { 4407 const PetscInt point = star[s]; 4408 4409 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4410 if (val == -1) { 4411 PetscInt *sstar = PETSC_NULL; 4412 PetscInt sstarSize, ss; 4413 PetscBool marked = PETSC_FALSE; 4414 4415 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4416 for (ss = 0; ss < sstarSize*2; ss += 2) { 4417 const PetscInt spoint = sstar[ss]; 4418 4419 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4420 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4421 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4422 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4423 if (val > 0) { 4424 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4425 } else { 4426 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4427 } 4428 marked = PETSC_TRUE; 4429 break; 4430 } 4431 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4432 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4433 } 4434 } 4435 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4436 } 4437 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4438 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4439 PetscFunctionReturn(0); 4440 } 4441 4442 #undef __FUNCT__ 4443 #define __FUNCT__ "DMPlexInterpolate_2D" 4444 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4445 { 4446 DM idm; 4447 DM_Plex *mesh; 4448 PetscHashIJ edgeTable; 4449 PetscInt *off; 4450 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4451 PetscInt numEdges, firstEdge, edge, e; 4452 PetscErrorCode ierr; 4453 4454 PetscFunctionBegin; 4455 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4456 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4457 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4458 numCells = cEnd - cStart; 4459 numVertices = vEnd - vStart; 4460 firstEdge = numCells + numVertices; 4461 numEdges = 0 ; 4462 /* Count edges using algorithm from CreateNeighborCSR */ 4463 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4464 if (off) { 4465 PetscInt numCorners = 0; 4466 4467 numEdges = off[numCells]/2; 4468 #if 0 4469 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4470 numEdges += 3*numCells - off[numCells]; 4471 #else 4472 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4473 for (c = cStart; c < cEnd; ++c) { 4474 PetscInt coneSize; 4475 4476 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4477 numCorners += coneSize; 4478 } 4479 numEdges += numCorners - off[numCells]; 4480 #endif 4481 } 4482 #if 0 4483 /* Check Euler characteristic V - E + F = 1 */ 4484 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4485 #endif 4486 /* Create interpolated mesh */ 4487 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4488 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4489 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4490 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4491 for (c = 0; c < numCells; ++c) { 4492 PetscInt numCorners; 4493 4494 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4495 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4496 } 4497 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4498 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4499 } 4500 ierr = DMSetUp(idm);CHKERRQ(ierr); 4501 /* Get edge cones from subsets of cell vertices */ 4502 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4503 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4504 4505 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4506 const PetscInt *cellFaces; 4507 PetscInt numCellFaces, faceSize, cf; 4508 4509 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4510 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4511 for (cf = 0; cf < numCellFaces; ++cf) { 4512 #if 1 4513 PetscHashIJKey key; 4514 4515 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4516 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4517 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4518 if (e < 0) { 4519 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4520 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4521 e = edge++; 4522 } 4523 #else 4524 PetscBool found = PETSC_FALSE; 4525 4526 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4527 for (e = firstEdge; e < edge; ++e) { 4528 const PetscInt *cone; 4529 4530 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4531 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4532 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4533 found = PETSC_TRUE; 4534 break; 4535 } 4536 } 4537 if (!found) { 4538 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4539 ++edge; 4540 } 4541 #endif 4542 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4543 } 4544 } 4545 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4546 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4547 ierr = PetscFree(off);CHKERRQ(ierr); 4548 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4549 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4550 mesh = (DM_Plex *) (idm)->data; 4551 /* Orient edges */ 4552 for (c = 0; c < numCells; ++c) { 4553 const PetscInt *cone = PETSC_NULL, *cellFaces; 4554 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4555 4556 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4557 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4558 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4559 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4560 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4561 for (cf = 0; cf < numCellFaces; ++cf) { 4562 const PetscInt *econe = PETSC_NULL; 4563 PetscInt esize; 4564 4565 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4566 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4567 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4568 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4569 /* Correctly oriented */ 4570 mesh->coneOrientations[coff+cf] = 0; 4571 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4572 /* Start at index 1, and reverse orientation */ 4573 mesh->coneOrientations[coff+cf] = -(1+1); 4574 } 4575 } 4576 } 4577 *dmInt = idm; 4578 PetscFunctionReturn(0); 4579 } 4580 4581 #undef __FUNCT__ 4582 #define __FUNCT__ "DMPlexInterpolate_3D" 4583 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4584 { 4585 DM idm, fdm; 4586 DM_Plex *mesh; 4587 PetscInt *off; 4588 const PetscInt numCorners = 4; 4589 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4590 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4591 PetscErrorCode ierr; 4592 4593 PetscFunctionBegin; 4594 { 4595 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4596 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4597 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4598 } 4599 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4600 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4601 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4602 numCells = cEnd - cStart; 4603 numVertices = vEnd - vStart; 4604 firstFace = numCells + numVertices; 4605 numFaces = 0 ; 4606 /* Count faces using algorithm from CreateNeighborCSR */ 4607 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4608 if (off) { 4609 numFaces = off[numCells]/2; 4610 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4611 numFaces += 4*numCells - off[numCells]; 4612 } 4613 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4614 firstEdge = firstFace + numFaces; 4615 numEdges = numVertices + numFaces - numCells - 1; 4616 /* Create interpolated mesh */ 4617 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4618 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4619 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4620 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4621 for (c = 0; c < numCells; ++c) { 4622 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4623 } 4624 for (f = firstFace; f < firstFace+numFaces; ++f) { 4625 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4626 } 4627 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4628 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4629 } 4630 ierr = DMSetUp(idm);CHKERRQ(ierr); 4631 /* Get face cones from subsets of cell vertices */ 4632 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4633 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4634 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4635 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4636 for (f = firstFace; f < firstFace+numFaces; ++f) { 4637 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4638 } 4639 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4640 for (c = 0, face = firstFace; c < numCells; ++c) { 4641 const PetscInt *cellFaces; 4642 PetscInt numCellFaces, faceSize, cf; 4643 4644 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4645 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4646 for (cf = 0; cf < numCellFaces; ++cf) { 4647 PetscBool found = PETSC_FALSE; 4648 4649 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4650 for (f = firstFace; f < face; ++f) { 4651 const PetscInt *cone = PETSC_NULL; 4652 4653 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4654 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4655 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4656 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4657 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4658 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4659 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4660 found = PETSC_TRUE; 4661 break; 4662 } 4663 } 4664 if (!found) { 4665 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4666 /* Save the vertices for orientation calculation */ 4667 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4668 ++face; 4669 } 4670 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4671 } 4672 } 4673 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4674 /* Get edge cones from subsets of face vertices */ 4675 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4676 const PetscInt *cellFaces; 4677 PetscInt numCellFaces, faceSize, cf; 4678 4679 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4680 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4681 for (cf = 0; cf < numCellFaces; ++cf) { 4682 PetscBool found = PETSC_FALSE; 4683 4684 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4685 for (e = firstEdge; e < edge; ++e) { 4686 const PetscInt *cone = PETSC_NULL; 4687 4688 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4689 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4690 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4691 found = PETSC_TRUE; 4692 break; 4693 } 4694 } 4695 if (!found) { 4696 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4697 ++edge; 4698 } 4699 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4700 } 4701 } 4702 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4703 ierr = PetscFree(off);CHKERRQ(ierr); 4704 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4705 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4706 mesh = (DM_Plex *) (idm)->data; 4707 /* Orient edges */ 4708 for (f = firstFace; f < firstFace+numFaces; ++f) { 4709 const PetscInt *cone, *cellFaces; 4710 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4711 4712 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4713 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4714 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4715 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4716 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4717 for (cf = 0; cf < numCellFaces; ++cf) { 4718 const PetscInt *econe; 4719 PetscInt esize; 4720 4721 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4722 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4723 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4724 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4725 /* Correctly oriented */ 4726 mesh->coneOrientations[coff+cf] = 0; 4727 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4728 /* Start at index 1, and reverse orientation */ 4729 mesh->coneOrientations[coff+cf] = -(1+1); 4730 } 4731 } 4732 } 4733 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4734 /* Orient faces */ 4735 for (c = 0; c < numCells; ++c) { 4736 const PetscInt *cone, *cellFaces; 4737 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4738 4739 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4740 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4741 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4742 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4743 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4744 for (cf = 0; cf < numCellFaces; ++cf) { 4745 PetscInt *origClosure = PETSC_NULL, *closure; 4746 PetscInt closureSize, i; 4747 4748 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4749 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4750 for (i = 4; i < 7; ++i) { 4751 if ((origClosure[i*2] < vStart) || (origClosure[i*2] >= vEnd)) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure point %D should be a vertex in [%D, %D)", origClosure[i*2], vStart, vEnd); 4752 } 4753 closure = &origClosure[4*2]; 4754 /* Remember that this is the orientation for edges, not vertices */ 4755 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4756 /* Correctly oriented */ 4757 mesh->coneOrientations[coff+cf] = 0; 4758 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4759 /* Shifted by 1 */ 4760 mesh->coneOrientations[coff+cf] = 1; 4761 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4762 /* Shifted by 2 */ 4763 mesh->coneOrientations[coff+cf] = 2; 4764 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4765 /* Start at edge 1, and reverse orientation */ 4766 mesh->coneOrientations[coff+cf] = -(1+1); 4767 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4768 /* Start at index 0, and reverse orientation */ 4769 mesh->coneOrientations[coff+cf] = -(0+1); 4770 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4771 /* Start at index 2, and reverse orientation */ 4772 mesh->coneOrientations[coff+cf] = -(2+1); 4773 } else SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Face %D did not match local face %D in cell %D for any orientation", cone[cf], cf, c); 4774 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4775 } 4776 } 4777 { 4778 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4779 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4780 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4781 } 4782 *dmInt = idm; 4783 PetscFunctionReturn(0); 4784 } 4785 4786 #undef __FUNCT__ 4787 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4788 /* 4789 This takes as input the common mesh generator output, a list of the vertices for each cell 4790 */ 4791 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4792 { 4793 PetscInt *cone, c, p; 4794 PetscErrorCode ierr; 4795 4796 PetscFunctionBegin; 4797 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4798 for (c = 0; c < numCells; ++c) { 4799 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4800 } 4801 ierr = DMSetUp(dm);CHKERRQ(ierr); 4802 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4803 for (c = 0; c < numCells; ++c) { 4804 for (p = 0; p < numCorners; ++p) { 4805 cone[p] = cells[c*numCorners+p]+numCells; 4806 } 4807 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4808 } 4809 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4810 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4811 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4812 PetscFunctionReturn(0); 4813 } 4814 4815 #undef __FUNCT__ 4816 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4817 /* 4818 This takes as input the coordinates for each vertex 4819 */ 4820 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4821 { 4822 PetscSection coordSection; 4823 Vec coordinates; 4824 PetscScalar *coords; 4825 PetscInt coordSize, v, d; 4826 PetscErrorCode ierr; 4827 4828 PetscFunctionBegin; 4829 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4830 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4831 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4832 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4833 for (v = numCells; v < numCells+numVertices; ++v) { 4834 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4835 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4836 } 4837 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4838 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4839 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4840 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4841 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4842 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4843 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4844 for (v = 0; v < numVertices; ++v) { 4845 for (d = 0; d < spaceDim; ++d) { 4846 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4847 } 4848 } 4849 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4850 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4851 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4852 PetscFunctionReturn(0); 4853 } 4854 4855 #undef __FUNCT__ 4856 #define __FUNCT__ "DMPlexCreateFromCellList" 4857 /* 4858 This takes as input the common mesh generator output, a list of the vertices for each cell 4859 */ 4860 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4861 { 4862 PetscErrorCode ierr; 4863 4864 PetscFunctionBegin; 4865 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4866 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4867 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4868 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4869 if (interpolate) { 4870 DM idm; 4871 4872 switch (dim) { 4873 case 2: 4874 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4875 case 3: 4876 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4877 default: 4878 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4879 } 4880 ierr = DMDestroy(dm);CHKERRQ(ierr); 4881 *dm = idm; 4882 } 4883 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4884 PetscFunctionReturn(0); 4885 } 4886 4887 #if defined(PETSC_HAVE_TRIANGLE) 4888 #include <triangle.h> 4889 4890 #undef __FUNCT__ 4891 #define __FUNCT__ "InitInput_Triangle" 4892 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4893 { 4894 PetscFunctionBegin; 4895 inputCtx->numberofpoints = 0; 4896 inputCtx->numberofpointattributes = 0; 4897 inputCtx->pointlist = PETSC_NULL; 4898 inputCtx->pointattributelist = PETSC_NULL; 4899 inputCtx->pointmarkerlist = PETSC_NULL; 4900 inputCtx->numberofsegments = 0; 4901 inputCtx->segmentlist = PETSC_NULL; 4902 inputCtx->segmentmarkerlist = PETSC_NULL; 4903 inputCtx->numberoftriangleattributes = 0; 4904 inputCtx->trianglelist = PETSC_NULL; 4905 inputCtx->numberofholes = 0; 4906 inputCtx->holelist = PETSC_NULL; 4907 inputCtx->numberofregions = 0; 4908 inputCtx->regionlist = PETSC_NULL; 4909 PetscFunctionReturn(0); 4910 } 4911 4912 #undef __FUNCT__ 4913 #define __FUNCT__ "InitOutput_Triangle" 4914 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4915 { 4916 PetscFunctionBegin; 4917 outputCtx->numberofpoints = 0; 4918 outputCtx->pointlist = PETSC_NULL; 4919 outputCtx->pointattributelist = PETSC_NULL; 4920 outputCtx->pointmarkerlist = PETSC_NULL; 4921 outputCtx->numberoftriangles = 0; 4922 outputCtx->trianglelist = PETSC_NULL; 4923 outputCtx->triangleattributelist = PETSC_NULL; 4924 outputCtx->neighborlist = PETSC_NULL; 4925 outputCtx->segmentlist = PETSC_NULL; 4926 outputCtx->segmentmarkerlist = PETSC_NULL; 4927 outputCtx->numberofedges = 0; 4928 outputCtx->edgelist = PETSC_NULL; 4929 outputCtx->edgemarkerlist = PETSC_NULL; 4930 PetscFunctionReturn(0); 4931 } 4932 4933 #undef __FUNCT__ 4934 #define __FUNCT__ "FiniOutput_Triangle" 4935 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4936 { 4937 PetscFunctionBegin; 4938 free(outputCtx->pointmarkerlist); 4939 free(outputCtx->edgelist); 4940 free(outputCtx->edgemarkerlist); 4941 free(outputCtx->trianglelist); 4942 free(outputCtx->neighborlist); 4943 PetscFunctionReturn(0); 4944 } 4945 4946 #undef __FUNCT__ 4947 #define __FUNCT__ "DMPlexGenerate_Triangle" 4948 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4949 { 4950 MPI_Comm comm = ((PetscObject) boundary)->comm; 4951 PetscInt dim = 2; 4952 const PetscBool createConvexHull = PETSC_FALSE; 4953 const PetscBool constrained = PETSC_FALSE; 4954 struct triangulateio in; 4955 struct triangulateio out; 4956 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4957 PetscMPIInt rank; 4958 PetscErrorCode ierr; 4959 4960 PetscFunctionBegin; 4961 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4962 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4963 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4964 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4965 in.numberofpoints = vEnd - vStart; 4966 if (in.numberofpoints > 0) { 4967 PetscSection coordSection; 4968 Vec coordinates; 4969 PetscScalar *array; 4970 4971 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4972 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4973 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4974 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4975 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4976 for (v = vStart; v < vEnd; ++v) { 4977 const PetscInt idx = v - vStart; 4978 PetscInt off, d; 4979 4980 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4981 for (d = 0; d < dim; ++d) { 4982 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4983 } 4984 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4985 } 4986 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4987 } 4988 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4989 in.numberofsegments = eEnd - eStart; 4990 if (in.numberofsegments > 0) { 4991 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4992 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4993 for (e = eStart; e < eEnd; ++e) { 4994 const PetscInt idx = e - eStart; 4995 const PetscInt *cone; 4996 4997 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4998 in.segmentlist[idx*2+0] = cone[0] - vStart; 4999 in.segmentlist[idx*2+1] = cone[1] - vStart; 5000 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5001 } 5002 } 5003 #if 0 /* Do not currently support holes */ 5004 PetscReal *holeCoords; 5005 PetscInt h, d; 5006 5007 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5008 if (in.numberofholes > 0) { 5009 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5010 for (h = 0; h < in.numberofholes; ++h) { 5011 for (d = 0; d < dim; ++d) { 5012 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5013 } 5014 } 5015 } 5016 #endif 5017 if (!rank) { 5018 char args[32]; 5019 5020 /* Take away 'Q' for verbose output */ 5021 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5022 if (createConvexHull) { 5023 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5024 } 5025 if (constrained) { 5026 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5027 } 5028 triangulate(args, &in, &out, PETSC_NULL); 5029 } 5030 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5031 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5032 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5033 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5034 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5035 5036 { 5037 const PetscInt numCorners = 3; 5038 const PetscInt numCells = out.numberoftriangles; 5039 const PetscInt numVertices = out.numberofpoints; 5040 const int *cells = out.trianglelist; 5041 const double *meshCoords = out.pointlist; 5042 5043 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5044 /* Set labels */ 5045 for (v = 0; v < numVertices; ++v) { 5046 if (out.pointmarkerlist[v]) { 5047 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5048 } 5049 } 5050 if (interpolate) { 5051 for (e = 0; e < out.numberofedges; e++) { 5052 if (out.edgemarkerlist[e]) { 5053 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5054 const PetscInt *edges; 5055 PetscInt numEdges; 5056 5057 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5058 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5059 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5060 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5061 } 5062 } 5063 } 5064 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5065 } 5066 #if 0 /* Do not currently support holes */ 5067 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5068 #endif 5069 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5070 PetscFunctionReturn(0); 5071 } 5072 5073 #undef __FUNCT__ 5074 #define __FUNCT__ "DMPlexRefine_Triangle" 5075 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5076 { 5077 MPI_Comm comm = ((PetscObject) dm)->comm; 5078 PetscInt dim = 2; 5079 struct triangulateio in; 5080 struct triangulateio out; 5081 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5082 PetscMPIInt rank; 5083 PetscErrorCode ierr; 5084 5085 PetscFunctionBegin; 5086 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5087 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5088 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5089 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5090 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5091 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5092 in.numberofpoints = vEnd - vStart; 5093 if (in.numberofpoints > 0) { 5094 PetscSection coordSection; 5095 Vec coordinates; 5096 PetscScalar *array; 5097 5098 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5099 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5100 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5101 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5102 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5103 for (v = vStart; v < vEnd; ++v) { 5104 const PetscInt idx = v - vStart; 5105 PetscInt off, d; 5106 5107 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5108 for (d = 0; d < dim; ++d) { 5109 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5110 } 5111 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5112 } 5113 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5114 } 5115 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5116 in.numberofcorners = 3; 5117 in.numberoftriangles = cEnd - cStart; 5118 in.trianglearealist = (double *) maxVolumes; 5119 if (in.numberoftriangles > 0) { 5120 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5121 for (c = cStart; c < cEnd; ++c) { 5122 const PetscInt idx = c - cStart; 5123 PetscInt *closure = PETSC_NULL; 5124 PetscInt closureSize; 5125 5126 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5127 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5128 for (v = 0; v < 3; ++v) { 5129 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5130 } 5131 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5132 } 5133 } 5134 /* TODO: Segment markers are missing on input */ 5135 #if 0 /* Do not currently support holes */ 5136 PetscReal *holeCoords; 5137 PetscInt h, d; 5138 5139 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5140 if (in.numberofholes > 0) { 5141 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5142 for (h = 0; h < in.numberofholes; ++h) { 5143 for (d = 0; d < dim; ++d) { 5144 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5145 } 5146 } 5147 } 5148 #endif 5149 if (!rank) { 5150 char args[32]; 5151 5152 /* Take away 'Q' for verbose output */ 5153 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5154 triangulate(args, &in, &out, PETSC_NULL); 5155 } 5156 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5157 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5158 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5159 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5160 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5161 5162 { 5163 const PetscInt numCorners = 3; 5164 const PetscInt numCells = out.numberoftriangles; 5165 const PetscInt numVertices = out.numberofpoints; 5166 const int *cells = out.trianglelist; 5167 const double *meshCoords = out.pointlist; 5168 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5169 5170 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5171 /* Set labels */ 5172 for (v = 0; v < numVertices; ++v) { 5173 if (out.pointmarkerlist[v]) { 5174 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5175 } 5176 } 5177 if (interpolate) { 5178 PetscInt e; 5179 5180 for (e = 0; e < out.numberofedges; e++) { 5181 if (out.edgemarkerlist[e]) { 5182 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5183 const PetscInt *edges; 5184 PetscInt numEdges; 5185 5186 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5187 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5188 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5189 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5190 } 5191 } 5192 } 5193 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5194 } 5195 #if 0 /* Do not currently support holes */ 5196 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5197 #endif 5198 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5199 PetscFunctionReturn(0); 5200 } 5201 #endif 5202 5203 #if defined(PETSC_HAVE_TETGEN) 5204 #include <tetgen.h> 5205 #undef __FUNCT__ 5206 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5207 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5208 { 5209 MPI_Comm comm = ((PetscObject) boundary)->comm; 5210 const PetscInt dim = 3; 5211 ::tetgenio in; 5212 ::tetgenio out; 5213 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5214 PetscMPIInt rank; 5215 PetscErrorCode ierr; 5216 5217 PetscFunctionBegin; 5218 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5219 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5220 in.numberofpoints = vEnd - vStart; 5221 if (in.numberofpoints > 0) { 5222 PetscSection coordSection; 5223 Vec coordinates; 5224 PetscScalar *array; 5225 5226 in.pointlist = new double[in.numberofpoints*dim]; 5227 in.pointmarkerlist = new int[in.numberofpoints]; 5228 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5229 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5230 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5231 for (v = vStart; v < vEnd; ++v) { 5232 const PetscInt idx = v - vStart; 5233 PetscInt off, d; 5234 5235 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5236 for (d = 0; d < dim; ++d) { 5237 in.pointlist[idx*dim + d] = array[off+d]; 5238 } 5239 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5240 } 5241 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5242 } 5243 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5244 in.numberoffacets = fEnd - fStart; 5245 if (in.numberoffacets > 0) { 5246 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5247 in.facetmarkerlist = new int[in.numberoffacets]; 5248 for (f = fStart; f < fEnd; ++f) { 5249 const PetscInt idx = f - fStart; 5250 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 5251 5252 in.facetlist[idx].numberofpolygons = 1; 5253 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5254 in.facetlist[idx].numberofholes = 0; 5255 in.facetlist[idx].holelist = NULL; 5256 5257 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5258 for (p = 0; p < numPoints*2; p += 2) { 5259 const PetscInt point = points[p]; 5260 if ((point >= vStart) && (point < vEnd)) { 5261 points[numVertices++] = point; 5262 } 5263 } 5264 5265 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5266 poly->numberofvertices = numVertices; 5267 poly->vertexlist = new int[poly->numberofvertices]; 5268 for (v = 0; v < numVertices; ++v) { 5269 const PetscInt vIdx = points[v] - vStart; 5270 poly->vertexlist[v] = vIdx; 5271 } 5272 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5273 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5274 } 5275 } 5276 if (!rank) { 5277 char args[32]; 5278 5279 /* Take away 'Q' for verbose output */ 5280 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5281 ::tetrahedralize(args, &in, &out); 5282 } 5283 { 5284 const PetscInt numCorners = 4; 5285 const PetscInt numCells = out.numberoftetrahedra; 5286 const PetscInt numVertices = out.numberofpoints; 5287 const int *cells = out.tetrahedronlist; 5288 const double *meshCoords = out.pointlist; 5289 5290 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5291 /* Set labels */ 5292 for (v = 0; v < numVertices; ++v) { 5293 if (out.pointmarkerlist[v]) { 5294 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5295 } 5296 } 5297 if (interpolate) { 5298 PetscInt e; 5299 5300 for (e = 0; e < out.numberofedges; e++) { 5301 if (out.edgemarkerlist[e]) { 5302 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5303 const PetscInt *edges; 5304 PetscInt numEdges; 5305 5306 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5307 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5308 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5309 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5310 } 5311 } 5312 for (f = 0; f < out.numberoftrifaces; f++) { 5313 if (out.trifacemarkerlist[f]) { 5314 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5315 const PetscInt *faces; 5316 PetscInt numFaces; 5317 5318 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5319 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5320 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5321 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5322 } 5323 } 5324 } 5325 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5326 } 5327 PetscFunctionReturn(0); 5328 } 5329 5330 #undef __FUNCT__ 5331 #define __FUNCT__ "DMPlexRefine_Tetgen" 5332 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5333 { 5334 MPI_Comm comm = ((PetscObject) dm)->comm; 5335 const PetscInt dim = 3; 5336 ::tetgenio in; 5337 ::tetgenio out; 5338 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5339 PetscMPIInt rank; 5340 PetscErrorCode ierr; 5341 5342 PetscFunctionBegin; 5343 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5344 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5345 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5346 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5347 in.numberofpoints = vEnd - vStart; 5348 if (in.numberofpoints > 0) { 5349 PetscSection coordSection; 5350 Vec coordinates; 5351 PetscScalar *array; 5352 5353 in.pointlist = new double[in.numberofpoints*dim]; 5354 in.pointmarkerlist = new int[in.numberofpoints]; 5355 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5356 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5357 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5358 for (v = vStart; v < vEnd; ++v) { 5359 const PetscInt idx = v - vStart; 5360 PetscInt off, d; 5361 5362 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5363 for (d = 0; d < dim; ++d) { 5364 in.pointlist[idx*dim + d] = array[off+d]; 5365 } 5366 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5367 } 5368 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5369 } 5370 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5371 in.numberofcorners = 4; 5372 in.numberoftetrahedra = cEnd - cStart; 5373 in.tetrahedronvolumelist = (double *) maxVolumes; 5374 if (in.numberoftetrahedra > 0) { 5375 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5376 for (c = cStart; c < cEnd; ++c) { 5377 const PetscInt idx = c - cStart; 5378 PetscInt *closure = PETSC_NULL; 5379 PetscInt closureSize; 5380 5381 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5382 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5383 for (v = 0; v < 4; ++v) { 5384 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5385 } 5386 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5387 } 5388 } 5389 /* TODO: Put in boundary faces with markers */ 5390 if (!rank) { 5391 char args[32]; 5392 5393 /* Take away 'Q' for verbose output */ 5394 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5395 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5396 ::tetrahedralize(args, &in, &out); 5397 } 5398 in.tetrahedronvolumelist = NULL; 5399 5400 { 5401 const PetscInt numCorners = 4; 5402 const PetscInt numCells = out.numberoftetrahedra; 5403 const PetscInt numVertices = out.numberofpoints; 5404 const int *cells = out.tetrahedronlist; 5405 const double *meshCoords = out.pointlist; 5406 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5407 5408 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5409 /* Set labels */ 5410 for (v = 0; v < numVertices; ++v) { 5411 if (out.pointmarkerlist[v]) { 5412 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5413 } 5414 } 5415 if (interpolate) { 5416 PetscInt e, f; 5417 5418 for (e = 0; e < out.numberofedges; e++) { 5419 if (out.edgemarkerlist[e]) { 5420 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5421 const PetscInt *edges; 5422 PetscInt numEdges; 5423 5424 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5425 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5426 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5427 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5428 } 5429 } 5430 for (f = 0; f < out.numberoftrifaces; f++) { 5431 if (out.trifacemarkerlist[f]) { 5432 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5433 const PetscInt *faces; 5434 PetscInt numFaces; 5435 5436 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5437 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5438 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5439 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5440 } 5441 } 5442 } 5443 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5444 } 5445 PetscFunctionReturn(0); 5446 } 5447 #endif 5448 5449 #if defined(PETSC_HAVE_CTETGEN) 5450 #include "ctetgen.h" 5451 5452 #undef __FUNCT__ 5453 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5454 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5455 { 5456 MPI_Comm comm = ((PetscObject) boundary)->comm; 5457 const PetscInt dim = 3; 5458 PLC *in, *out; 5459 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5460 PetscMPIInt rank; 5461 PetscErrorCode ierr; 5462 5463 PetscFunctionBegin; 5464 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5465 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5466 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5467 ierr = PLCCreate(&in);CHKERRQ(ierr); 5468 ierr = PLCCreate(&out);CHKERRQ(ierr); 5469 in->numberofpoints = vEnd - vStart; 5470 if (in->numberofpoints > 0) { 5471 PetscSection coordSection; 5472 Vec coordinates; 5473 PetscScalar *array; 5474 5475 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5476 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5477 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5478 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5479 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5480 for (v = vStart; v < vEnd; ++v) { 5481 const PetscInt idx = v - vStart; 5482 PetscInt off, d, m; 5483 5484 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5485 for (d = 0; d < dim; ++d) { 5486 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5487 } 5488 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5489 in->pointmarkerlist[idx] = (int) m; 5490 } 5491 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5492 } 5493 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5494 in->numberoffacets = fEnd - fStart; 5495 if (in->numberoffacets > 0) { 5496 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5497 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5498 for (f = fStart; f < fEnd; ++f) { 5499 const PetscInt idx = f - fStart; 5500 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 5501 polygon *poly; 5502 5503 in->facetlist[idx].numberofpolygons = 1; 5504 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5505 in->facetlist[idx].numberofholes = 0; 5506 in->facetlist[idx].holelist = PETSC_NULL; 5507 5508 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5509 for (p = 0; p < numPoints*2; p += 2) { 5510 const PetscInt point = points[p]; 5511 if ((point >= vStart) && (point < vEnd)) { 5512 points[numVertices++] = point; 5513 } 5514 } 5515 5516 poly = in->facetlist[idx].polygonlist; 5517 poly->numberofvertices = numVertices; 5518 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5519 for (v = 0; v < numVertices; ++v) { 5520 const PetscInt vIdx = points[v] - vStart; 5521 poly->vertexlist[v] = vIdx; 5522 } 5523 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5524 in->facetmarkerlist[idx] = (int) m; 5525 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5526 } 5527 } 5528 if (!rank) { 5529 TetGenOpts t; 5530 5531 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5532 t.in = boundary; /* Should go away */ 5533 t.plc = 1; 5534 t.quality = 1; 5535 t.edgesout = 1; 5536 t.zeroindex = 1; 5537 t.quiet = 1; 5538 t.verbose = verbose; 5539 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5540 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5541 } 5542 { 5543 const PetscInt numCorners = 4; 5544 const PetscInt numCells = out->numberoftetrahedra; 5545 const PetscInt numVertices = out->numberofpoints; 5546 const int *cells = out->tetrahedronlist; 5547 const double *meshCoords = out->pointlist; 5548 5549 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5550 /* Set labels */ 5551 for (v = 0; v < numVertices; ++v) { 5552 if (out->pointmarkerlist[v]) { 5553 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5554 } 5555 } 5556 if (interpolate) { 5557 PetscInt e; 5558 5559 for (e = 0; e < out->numberofedges; e++) { 5560 if (out->edgemarkerlist[e]) { 5561 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5562 const PetscInt *edges; 5563 PetscInt numEdges; 5564 5565 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5566 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5567 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5568 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5569 } 5570 } 5571 for (f = 0; f < out->numberoftrifaces; f++) { 5572 if (out->trifacemarkerlist[f]) { 5573 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5574 const PetscInt *faces; 5575 PetscInt numFaces; 5576 5577 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5578 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5579 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5580 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5581 } 5582 } 5583 } 5584 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5585 } 5586 5587 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5588 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5589 PetscFunctionReturn(0); 5590 } 5591 5592 #undef __FUNCT__ 5593 #define __FUNCT__ "DMPlexRefine_CTetgen" 5594 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5595 { 5596 MPI_Comm comm = ((PetscObject) dm)->comm; 5597 const PetscInt dim = 3; 5598 PLC *in, *out; 5599 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5600 PetscMPIInt rank; 5601 PetscErrorCode ierr; 5602 5603 PetscFunctionBegin; 5604 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5605 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5606 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5607 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5608 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5609 ierr = PLCCreate(&in);CHKERRQ(ierr); 5610 ierr = PLCCreate(&out);CHKERRQ(ierr); 5611 in->numberofpoints = vEnd - vStart; 5612 if (in->numberofpoints > 0) { 5613 PetscSection coordSection; 5614 Vec coordinates; 5615 PetscScalar *array; 5616 5617 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5618 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5619 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5620 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5621 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5622 for (v = vStart; v < vEnd; ++v) { 5623 const PetscInt idx = v - vStart; 5624 PetscInt off, d, m; 5625 5626 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5627 for (d = 0; d < dim; ++d) { 5628 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5629 } 5630 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5631 in->pointmarkerlist[idx] = (int) m; 5632 } 5633 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5634 } 5635 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5636 in->numberofcorners = 4; 5637 in->numberoftetrahedra = cEnd - cStart; 5638 in->tetrahedronvolumelist = maxVolumes; 5639 if (in->numberoftetrahedra > 0) { 5640 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5641 for (c = cStart; c < cEnd; ++c) { 5642 const PetscInt idx = c - cStart; 5643 PetscInt *closure = PETSC_NULL; 5644 PetscInt closureSize; 5645 5646 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5647 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5648 for (v = 0; v < 4; ++v) { 5649 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5650 } 5651 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5652 } 5653 } 5654 if (!rank) { 5655 TetGenOpts t; 5656 5657 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5658 t.in = dm; /* Should go away */ 5659 t.refine = 1; 5660 t.varvolume = 1; 5661 t.quality = 1; 5662 t.edgesout = 1; 5663 t.zeroindex = 1; 5664 t.quiet = 1; 5665 t.verbose = verbose; /* Change this */ 5666 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5667 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5668 } 5669 { 5670 const PetscInt numCorners = 4; 5671 const PetscInt numCells = out->numberoftetrahedra; 5672 const PetscInt numVertices = out->numberofpoints; 5673 const int *cells = out->tetrahedronlist; 5674 const double *meshCoords = out->pointlist; 5675 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5676 5677 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5678 /* Set labels */ 5679 for (v = 0; v < numVertices; ++v) { 5680 if (out->pointmarkerlist[v]) { 5681 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5682 } 5683 } 5684 if (interpolate) { 5685 PetscInt e, f; 5686 5687 for (e = 0; e < out->numberofedges; e++) { 5688 if (out->edgemarkerlist[e]) { 5689 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5690 const PetscInt *edges; 5691 PetscInt numEdges; 5692 5693 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5694 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5695 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5696 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5697 } 5698 } 5699 for (f = 0; f < out->numberoftrifaces; f++) { 5700 if (out->trifacemarkerlist[f]) { 5701 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5702 const PetscInt *faces; 5703 PetscInt numFaces; 5704 5705 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5706 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5707 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5708 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5709 } 5710 } 5711 } 5712 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5713 } 5714 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5715 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5716 PetscFunctionReturn(0); 5717 } 5718 #endif 5719 5720 #undef __FUNCT__ 5721 #define __FUNCT__ "DMPlexGenerate" 5722 /*@C 5723 DMPlexGenerate - Generates a mesh. 5724 5725 Not Collective 5726 5727 Input Parameters: 5728 + boundary - The DMPlex boundary object 5729 . name - The mesh generation package name 5730 - interpolate - Flag to create intermediate mesh elements 5731 5732 Output Parameter: 5733 . mesh - The DMPlex object 5734 5735 Level: intermediate 5736 5737 .keywords: mesh, elements 5738 .seealso: DMPlexCreate(), DMRefine() 5739 @*/ 5740 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5741 { 5742 PetscInt dim; 5743 char genname[1024]; 5744 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5745 PetscErrorCode ierr; 5746 5747 PetscFunctionBegin; 5748 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5749 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5750 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5751 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5752 if (flg) {name = genname;} 5753 if (name) { 5754 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5755 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5756 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5757 } 5758 switch (dim) { 5759 case 1: 5760 if (!name || isTriangle) { 5761 #if defined(PETSC_HAVE_TRIANGLE) 5762 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5763 #else 5764 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5765 #endif 5766 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5767 break; 5768 case 2: 5769 if (!name || isCTetgen) { 5770 #if defined(PETSC_HAVE_CTETGEN) 5771 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5772 #else 5773 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5774 #endif 5775 } else if (isTetgen) { 5776 #if defined(PETSC_HAVE_TETGEN) 5777 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5778 #else 5779 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5780 #endif 5781 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5782 break; 5783 default: 5784 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5785 } 5786 PetscFunctionReturn(0); 5787 } 5788 5789 typedef PetscInt CellRefiner; 5790 5791 #undef __FUNCT__ 5792 #define __FUNCT__ "GetDepthStart_Private" 5793 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5794 { 5795 PetscFunctionBegin; 5796 if (cStart) *cStart = 0; 5797 if (vStart) *vStart = depthSize[depth]; 5798 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5799 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5800 PetscFunctionReturn(0); 5801 } 5802 5803 #undef __FUNCT__ 5804 #define __FUNCT__ "GetDepthEnd_Private" 5805 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5806 { 5807 PetscFunctionBegin; 5808 if (cEnd) *cEnd = depthSize[depth]; 5809 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5810 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5811 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5812 PetscFunctionReturn(0); 5813 } 5814 5815 #undef __FUNCT__ 5816 #define __FUNCT__ "CellRefinerGetSizes" 5817 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5818 { 5819 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5820 PetscErrorCode ierr; 5821 5822 PetscFunctionBegin; 5823 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5824 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5825 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5826 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5827 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5828 switch (refiner) { 5829 case 1: 5830 /* Simplicial 2D */ 5831 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5832 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5833 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5834 break; 5835 case 3: 5836 /* Hybrid 2D */ 5837 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5838 cMax = PetscMin(cEnd, cMax); 5839 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5840 fMax = PetscMin(fEnd, fMax); 5841 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5842 depthSize[1] = 2*(fMax - fStart) + 3*(cMax - cStart) + (fEnd - fMax) + (cEnd - cMax); /* Every interior face is split into 2 faces, 3 faces are added for each interior cell, and one in each hybrid cell */ 5843 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5844 break; 5845 case 2: 5846 /* Hex 2D */ 5847 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5848 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5849 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5850 break; 5851 default: 5852 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5853 } 5854 PetscFunctionReturn(0); 5855 } 5856 5857 #undef __FUNCT__ 5858 #define __FUNCT__ "CellRefinerSetConeSizes" 5859 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5860 { 5861 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5862 PetscErrorCode ierr; 5863 5864 PetscFunctionBegin; 5865 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5866 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5867 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5868 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5869 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5870 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5871 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5872 switch (refiner) { 5873 case 1: 5874 /* Simplicial 2D */ 5875 /* All cells have 3 faces */ 5876 for (c = cStart; c < cEnd; ++c) { 5877 for (r = 0; r < 4; ++r) { 5878 const PetscInt newp = (c - cStart)*4 + r; 5879 5880 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5881 } 5882 } 5883 /* Split faces have 2 vertices and the same cells as the parent */ 5884 for (f = fStart; f < fEnd; ++f) { 5885 for (r = 0; r < 2; ++r) { 5886 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5887 PetscInt size; 5888 5889 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5890 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5891 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5892 } 5893 } 5894 /* Interior faces have 2 vertices and 2 cells */ 5895 for (c = cStart; c < cEnd; ++c) { 5896 for (r = 0; r < 3; ++r) { 5897 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5898 5899 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5900 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5901 } 5902 } 5903 /* Old vertices have identical supports */ 5904 for (v = vStart; v < vEnd; ++v) { 5905 const PetscInt newp = vStartNew + (v - vStart); 5906 PetscInt size; 5907 5908 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5909 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5910 } 5911 /* Face vertices have 2 + cells*2 supports */ 5912 for (f = fStart; f < fEnd; ++f) { 5913 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5914 PetscInt size; 5915 5916 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5917 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5918 } 5919 break; 5920 case 2: 5921 /* Hex 2D */ 5922 /* All cells have 4 faces */ 5923 for (c = cStart; c < cEnd; ++c) { 5924 for (r = 0; r < 4; ++r) { 5925 const PetscInt newp = (c - cStart)*4 + r; 5926 5927 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5928 } 5929 } 5930 /* Split faces have 2 vertices and the same cells as the parent */ 5931 for (f = fStart; f < fEnd; ++f) { 5932 for (r = 0; r < 2; ++r) { 5933 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5934 PetscInt size; 5935 5936 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5937 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5938 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5939 } 5940 } 5941 /* Interior faces have 2 vertices and 2 cells */ 5942 for (c = cStart; c < cEnd; ++c) { 5943 for (r = 0; r < 4; ++r) { 5944 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5945 5946 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5947 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5948 } 5949 } 5950 /* Old vertices have identical supports */ 5951 for (v = vStart; v < vEnd; ++v) { 5952 const PetscInt newp = vStartNew + (v - vStart); 5953 PetscInt size; 5954 5955 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5956 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5957 } 5958 /* Face vertices have 2 + cells supports */ 5959 for (f = fStart; f < fEnd; ++f) { 5960 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5961 PetscInt size; 5962 5963 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5964 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5965 } 5966 /* Cell vertices have 4 supports */ 5967 for (c = cStart; c < cEnd; ++c) { 5968 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5969 5970 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5971 } 5972 break; 5973 case 3: 5974 /* Hybrid 2D */ 5975 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5976 cMax = PetscMin(cEnd, cMax); 5977 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5978 fMax = PetscMin(fEnd, fMax); 5979 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5980 /* Interior cells have 3 faces */ 5981 for (c = cStart; c < cMax; ++c) { 5982 for (r = 0; r < 4; ++r) { 5983 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5984 5985 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5986 } 5987 } 5988 /* Hybrid cells have 4 faces */ 5989 for (c = cMax; c < cEnd; ++c) { 5990 for (r = 0; r < 2; ++r) { 5991 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5992 5993 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5994 } 5995 } 5996 /* Interior split faces have 2 vertices and the same cells as the parent */ 5997 for (f = fStart; f < fMax; ++f) { 5998 for (r = 0; r < 2; ++r) { 5999 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6000 PetscInt size; 6001 6002 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6003 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6004 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6005 } 6006 } 6007 /* Interior cell faces have 2 vertices and 2 cells */ 6008 for (c = cStart; c < cMax; ++c) { 6009 for (r = 0; r < 3; ++r) { 6010 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6011 6012 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6013 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6014 } 6015 } 6016 /* Hybrid faces have 2 vertices and the same cells */ 6017 for (f = fMax; f < fEnd; ++f) { 6018 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6019 PetscInt size; 6020 6021 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6022 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6023 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6024 } 6025 /* Hybrid cell faces have 2 vertices and 2 cells */ 6026 for (c = cMax; c < cEnd; ++c) { 6027 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6028 6029 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6030 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6031 } 6032 /* Old vertices have identical supports */ 6033 for (v = vStart; v < vEnd; ++v) { 6034 const PetscInt newp = vStartNew + (v - vStart); 6035 PetscInt size; 6036 6037 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6038 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6039 } 6040 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6041 for (f = fStart; f < fMax; ++f) { 6042 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6043 const PetscInt *support; 6044 PetscInt size, newSize = 2, s; 6045 6046 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6047 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6048 for (s = 0; s < size; ++s) { 6049 if (support[s] >= cMax) { 6050 newSize += 1; 6051 } else { 6052 newSize += 2; 6053 } 6054 } 6055 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6056 } 6057 break; 6058 default: 6059 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6060 } 6061 PetscFunctionReturn(0); 6062 } 6063 6064 #undef __FUNCT__ 6065 #define __FUNCT__ "CellRefinerSetCones" 6066 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6067 { 6068 PetscInt depth, cStart, cEnd, cMax, cStartNew, cEndNew, c, vStart, vEnd, vMax, vStartNew, vEndNew, v, fStart, fEnd, fMax, fStartNew, fEndNew, f, eStart, eEnd, eMax, eStartNew, eEndNew, r, p; 6069 PetscInt maxSupportSize, *supportRef; 6070 PetscErrorCode ierr; 6071 6072 PetscFunctionBegin; 6073 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6074 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6075 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6076 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6077 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6078 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6079 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6080 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6081 switch (refiner) { 6082 case 1: 6083 /* Simplicial 2D */ 6084 /* 6085 2 6086 |\ 6087 | \ 6088 | \ 6089 | \ 6090 | C \ 6091 | \ 6092 | \ 6093 2---1---1 6094 |\ D / \ 6095 | 2 0 \ 6096 |A \ / B \ 6097 0---0-------1 6098 */ 6099 /* All cells have 3 faces */ 6100 for (c = cStart; c < cEnd; ++c) { 6101 const PetscInt newp = cStartNew + (c - cStart)*4; 6102 const PetscInt *cone, *ornt; 6103 PetscInt coneNew[3], orntNew[3]; 6104 6105 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6106 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6107 /* A triangle */ 6108 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6109 orntNew[0] = ornt[0]; 6110 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6111 orntNew[1] = -2; 6112 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6113 orntNew[2] = ornt[2]; 6114 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6115 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6116 #if 1 6117 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6118 for (p = 0; p < 3; ++p) { 6119 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6120 } 6121 #endif 6122 /* B triangle */ 6123 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6124 orntNew[0] = ornt[0]; 6125 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6126 orntNew[1] = ornt[1]; 6127 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6128 orntNew[2] = -2; 6129 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6130 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6131 #if 1 6132 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6133 for (p = 0; p < 3; ++p) { 6134 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6135 } 6136 #endif 6137 /* C triangle */ 6138 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6139 orntNew[0] = -2; 6140 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6141 orntNew[1] = ornt[1]; 6142 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6143 orntNew[2] = ornt[2]; 6144 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6145 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6146 #if 1 6147 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6148 for (p = 0; p < 3; ++p) { 6149 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6150 } 6151 #endif 6152 /* D triangle */ 6153 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6154 orntNew[0] = 0; 6155 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6156 orntNew[1] = 0; 6157 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6158 orntNew[2] = 0; 6159 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6160 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6161 #if 1 6162 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6163 for (p = 0; p < 3; ++p) { 6164 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6165 } 6166 #endif 6167 } 6168 /* Split faces have 2 vertices and the same cells as the parent */ 6169 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6170 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6171 for (f = fStart; f < fEnd; ++f) { 6172 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6173 6174 for (r = 0; r < 2; ++r) { 6175 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6176 const PetscInt *cone, *support; 6177 PetscInt coneNew[2], coneSize, c, supportSize, s; 6178 6179 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6180 coneNew[0] = vStartNew + (cone[0] - vStart); 6181 coneNew[1] = vStartNew + (cone[1] - vStart); 6182 coneNew[(r+1)%2] = newv; 6183 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6184 #if 1 6185 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6186 for (p = 0; p < 2; ++p) { 6187 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6188 } 6189 #endif 6190 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6191 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6192 for (s = 0; s < supportSize; ++s) { 6193 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6194 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6195 for (c = 0; c < coneSize; ++c) { 6196 if (cone[c] == f) { 6197 break; 6198 } 6199 } 6200 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6201 } 6202 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6203 #if 1 6204 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6205 for (p = 0; p < supportSize; ++p) { 6206 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6207 } 6208 #endif 6209 } 6210 } 6211 /* Interior faces have 2 vertices and 2 cells */ 6212 for (c = cStart; c < cEnd; ++c) { 6213 const PetscInt *cone; 6214 6215 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6216 for (r = 0; r < 3; ++r) { 6217 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6218 PetscInt coneNew[2]; 6219 PetscInt supportNew[2]; 6220 6221 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6222 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6223 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6224 #if 1 6225 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6226 for (p = 0; p < 2; ++p) { 6227 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6228 } 6229 #endif 6230 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6231 supportNew[1] = (c - cStart)*4 + 3; 6232 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6233 #if 1 6234 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6235 for (p = 0; p < 2; ++p) { 6236 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6237 } 6238 #endif 6239 } 6240 } 6241 /* Old vertices have identical supports */ 6242 for (v = vStart; v < vEnd; ++v) { 6243 const PetscInt newp = vStartNew + (v - vStart); 6244 const PetscInt *support, *cone; 6245 PetscInt size, s; 6246 6247 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6248 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6249 for (s = 0; s < size; ++s) { 6250 PetscInt r = 0; 6251 6252 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6253 if (cone[1] == v) r = 1; 6254 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6255 } 6256 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6257 #if 1 6258 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6259 for (p = 0; p < size; ++p) { 6260 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6261 } 6262 #endif 6263 } 6264 /* Face vertices have 2 + cells*2 supports */ 6265 for (f = fStart; f < fEnd; ++f) { 6266 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6267 const PetscInt *cone, *support; 6268 PetscInt size, s; 6269 6270 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6271 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6272 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6273 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6274 for (s = 0; s < size; ++s) { 6275 PetscInt r = 0; 6276 6277 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6278 if (cone[1] == f) r = 1; 6279 else if (cone[2] == f) r = 2; 6280 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6281 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6282 } 6283 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6284 #if 1 6285 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6286 for (p = 0; p < 2+size*2; ++p) { 6287 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6288 } 6289 #endif 6290 } 6291 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6292 break; 6293 case 2: 6294 /* Hex 2D */ 6295 /* 6296 3---------2---------2 6297 | | | 6298 | D 2 C | 6299 | | | 6300 3----3----0----1----1 6301 | | | 6302 | A 0 B | 6303 | | | 6304 0---------0---------1 6305 */ 6306 /* All cells have 4 faces */ 6307 for (c = cStart; c < cEnd; ++c) { 6308 const PetscInt newp = (c - cStart)*4; 6309 const PetscInt *cone, *ornt; 6310 PetscInt coneNew[4], orntNew[4]; 6311 6312 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6313 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6314 /* A quad */ 6315 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6316 orntNew[0] = ornt[0]; 6317 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6318 orntNew[1] = 0; 6319 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6320 orntNew[2] = -2; 6321 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6322 orntNew[3] = ornt[3]; 6323 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6324 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6325 #if 1 6326 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6327 for (p = 0; p < 4; ++p) { 6328 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6329 } 6330 #endif 6331 /* B quad */ 6332 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6333 orntNew[0] = ornt[0]; 6334 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6335 orntNew[1] = ornt[1]; 6336 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6337 orntNew[2] = 0; 6338 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6339 orntNew[3] = -2; 6340 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6341 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6342 #if 1 6343 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6344 for (p = 0; p < 4; ++p) { 6345 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6346 } 6347 #endif 6348 /* C quad */ 6349 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6350 orntNew[0] = -2; 6351 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6352 orntNew[1] = ornt[1]; 6353 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6354 orntNew[2] = ornt[2]; 6355 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6356 orntNew[3] = 0; 6357 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6358 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6359 #if 1 6360 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6361 for (p = 0; p < 4; ++p) { 6362 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6363 } 6364 #endif 6365 /* D quad */ 6366 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6367 orntNew[0] = 0; 6368 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6369 orntNew[1] = -2; 6370 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6371 orntNew[2] = ornt[2]; 6372 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6373 orntNew[3] = ornt[3]; 6374 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6375 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6376 #if 1 6377 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6378 for (p = 0; p < 4; ++p) { 6379 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6380 } 6381 #endif 6382 } 6383 /* Split faces have 2 vertices and the same cells as the parent */ 6384 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6385 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6386 for (f = fStart; f < fEnd; ++f) { 6387 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6388 6389 for (r = 0; r < 2; ++r) { 6390 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6391 const PetscInt *cone, *support; 6392 PetscInt coneNew[2], coneSize, c, supportSize, s; 6393 6394 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6395 coneNew[0] = vStartNew + (cone[0] - vStart); 6396 coneNew[1] = vStartNew + (cone[1] - vStart); 6397 coneNew[(r+1)%2] = newv; 6398 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6399 #if 1 6400 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6401 for (p = 0; p < 2; ++p) { 6402 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6403 } 6404 #endif 6405 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6406 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6407 for (s = 0; s < supportSize; ++s) { 6408 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6409 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6410 for (c = 0; c < coneSize; ++c) { 6411 if (cone[c] == f) { 6412 break; 6413 } 6414 } 6415 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6416 } 6417 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6418 #if 1 6419 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6420 for (p = 0; p < supportSize; ++p) { 6421 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6422 } 6423 #endif 6424 } 6425 } 6426 /* Interior faces have 2 vertices and 2 cells */ 6427 for (c = cStart; c < cEnd; ++c) { 6428 const PetscInt *cone; 6429 PetscInt coneNew[2], supportNew[2]; 6430 6431 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6432 for (r = 0; r < 4; ++r) { 6433 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6434 6435 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6436 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6437 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6438 #if 1 6439 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6440 for (p = 0; p < 2; ++p) { 6441 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6442 } 6443 #endif 6444 supportNew[0] = (c - cStart)*4 + r; 6445 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6446 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6447 #if 1 6448 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6449 for (p = 0; p < 2; ++p) { 6450 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6451 } 6452 #endif 6453 } 6454 } 6455 /* Old vertices have identical supports */ 6456 for (v = vStart; v < vEnd; ++v) { 6457 const PetscInt newp = vStartNew + (v - vStart); 6458 const PetscInt *support, *cone; 6459 PetscInt size, s; 6460 6461 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6462 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6463 for (s = 0; s < size; ++s) { 6464 PetscInt r = 0; 6465 6466 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6467 if (cone[1] == v) r = 1; 6468 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6469 } 6470 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6471 #if 1 6472 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6473 for (p = 0; p < size; ++p) { 6474 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6475 } 6476 #endif 6477 } 6478 /* Face vertices have 2 + cells supports */ 6479 for (f = fStart; f < fEnd; ++f) { 6480 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6481 const PetscInt *cone, *support; 6482 PetscInt size, s; 6483 6484 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6485 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6486 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6487 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6488 for (s = 0; s < size; ++s) { 6489 PetscInt r = 0; 6490 6491 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6492 if (cone[1] == f) r = 1; 6493 else if (cone[2] == f) r = 2; 6494 else if (cone[3] == f) r = 3; 6495 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6496 } 6497 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6498 #if 1 6499 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6500 for (p = 0; p < 2+size; ++p) { 6501 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6502 } 6503 #endif 6504 } 6505 /* Cell vertices have 4 supports */ 6506 for (c = cStart; c < cEnd; ++c) { 6507 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6508 PetscInt supportNew[4]; 6509 6510 for (r = 0; r < 4; ++r) { 6511 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6512 } 6513 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6514 } 6515 break; 6516 case 3: 6517 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6518 cMax = PetscMin(cEnd, cMax); 6519 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6520 fMax = PetscMin(fEnd, fMax); 6521 /* Interior cells have 3 faces */ 6522 for (c = cStart; c < cMax; ++c) { 6523 const PetscInt newp = cStartNew + (c - cStart)*4; 6524 const PetscInt *cone, *ornt; 6525 PetscInt coneNew[3], orntNew[3]; 6526 6527 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6528 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6529 /* A triangle */ 6530 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6531 orntNew[0] = ornt[0]; 6532 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6533 orntNew[1] = -2; 6534 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6535 orntNew[2] = ornt[2]; 6536 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6537 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6538 #if 1 6539 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6540 for (p = 0; p < 3; ++p) { 6541 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6542 } 6543 #endif 6544 /* B triangle */ 6545 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6546 orntNew[0] = ornt[0]; 6547 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6548 orntNew[1] = ornt[1]; 6549 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6550 orntNew[2] = -2; 6551 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6552 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6553 #if 1 6554 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6555 for (p = 0; p < 3; ++p) { 6556 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6557 } 6558 #endif 6559 /* C triangle */ 6560 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6561 orntNew[0] = -2; 6562 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6563 orntNew[1] = ornt[1]; 6564 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6565 orntNew[2] = ornt[2]; 6566 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6567 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6568 #if 1 6569 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6570 for (p = 0; p < 3; ++p) { 6571 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6572 } 6573 #endif 6574 /* D triangle */ 6575 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6576 orntNew[0] = 0; 6577 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6578 orntNew[1] = 0; 6579 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6580 orntNew[2] = 0; 6581 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6582 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6583 #if 1 6584 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6585 for (p = 0; p < 3; ++p) { 6586 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6587 } 6588 #endif 6589 } 6590 /* 6591 2----3----3 6592 | | 6593 | B | 6594 | | 6595 0----4--- 1 6596 | | 6597 | A | 6598 | | 6599 0----2----1 6600 */ 6601 /* Hybrid cells have 4 faces */ 6602 for (c = cMax; c < cEnd; ++c) { 6603 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6604 const PetscInt *cone, *ornt; 6605 PetscInt coneNew[4], orntNew[4]; 6606 6607 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6608 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6609 /* A quad */ 6610 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6611 orntNew[0] = ornt[0]; 6612 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6613 orntNew[1] = ornt[1]; 6614 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6615 orntNew[2] = 0; 6616 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6617 orntNew[3] = 0; 6618 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6619 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6620 #if 1 6621 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6622 for (p = 0; p < 4; ++p) { 6623 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6624 } 6625 #endif 6626 /* B quad */ 6627 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6628 orntNew[0] = ornt[0]; 6629 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6630 orntNew[1] = ornt[1]; 6631 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6632 orntNew[2] = 0; 6633 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6634 orntNew[3] = 0; 6635 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6636 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6637 #if 1 6638 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6639 for (p = 0; p < 4; ++p) { 6640 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6641 } 6642 #endif 6643 } 6644 /* Interior split faces have 2 vertices and the same cells as the parent */ 6645 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6646 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6647 for (f = fStart; f < fMax; ++f) { 6648 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6649 6650 for (r = 0; r < 2; ++r) { 6651 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6652 const PetscInt *cone, *support; 6653 PetscInt coneNew[2], coneSize, c, supportSize, s; 6654 6655 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6656 coneNew[0] = vStartNew + (cone[0] - vStart); 6657 coneNew[1] = vStartNew + (cone[1] - vStart); 6658 coneNew[(r+1)%2] = newv; 6659 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6660 #if 1 6661 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6662 for (p = 0; p < 2; ++p) { 6663 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6664 } 6665 #endif 6666 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6667 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6668 for (s = 0; s < supportSize; ++s) { 6669 if (support[s] >= cMax) { 6670 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6671 } else { 6672 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6673 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6674 for (c = 0; c < coneSize; ++c) { 6675 if (cone[c] == f) { 6676 break; 6677 } 6678 } 6679 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6680 } 6681 } 6682 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6683 #if 1 6684 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6685 for (p = 0; p < supportSize; ++p) { 6686 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6687 } 6688 #endif 6689 } 6690 } 6691 /* Interior cell faces have 2 vertices and 2 cells */ 6692 for (c = cStart; c < cMax; ++c) { 6693 const PetscInt *cone; 6694 6695 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6696 for (r = 0; r < 3; ++r) { 6697 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6698 PetscInt coneNew[2]; 6699 PetscInt supportNew[2]; 6700 6701 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6702 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6703 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6704 #if 1 6705 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6706 for (p = 0; p < 2; ++p) { 6707 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6708 } 6709 #endif 6710 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6711 supportNew[1] = (c - cStart)*4 + 3; 6712 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6713 #if 1 6714 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6715 for (p = 0; p < 2; ++p) { 6716 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6717 } 6718 #endif 6719 } 6720 } 6721 /* Interior hybrid faces have 2 vertices and the same cells */ 6722 for (f = fMax; f < fEnd; ++f) { 6723 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6724 const PetscInt *cone; 6725 const PetscInt *support; 6726 PetscInt coneNew[2]; 6727 PetscInt supportNew[2]; 6728 PetscInt size, s, r; 6729 6730 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6731 coneNew[0] = vStartNew + (cone[0] - vStart); 6732 coneNew[1] = vStartNew + (cone[1] - vStart); 6733 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6734 #if 1 6735 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6736 for (p = 0; p < 2; ++p) { 6737 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6738 } 6739 #endif 6740 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6741 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6742 for (s = 0; s < size; ++s) { 6743 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6744 for (r = 0; r < 2; ++r) { 6745 if (cone[r+2] == f) break; 6746 } 6747 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6748 } 6749 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6750 #if 1 6751 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6752 for (p = 0; p < size; ++p) { 6753 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6754 } 6755 #endif 6756 } 6757 /* Cell hybrid faces have 2 vertices and 2 cells */ 6758 for (c = cMax; c < cEnd; ++c) { 6759 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6760 const PetscInt *cone; 6761 PetscInt coneNew[2]; 6762 PetscInt supportNew[2]; 6763 6764 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6765 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6766 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6767 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6768 #if 1 6769 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6770 for (p = 0; p < 2; ++p) { 6771 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6772 } 6773 #endif 6774 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6775 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6776 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6777 #if 1 6778 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6779 for (p = 0; p < 2; ++p) { 6780 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6781 } 6782 #endif 6783 } 6784 /* Old vertices have identical supports */ 6785 for (v = vStart; v < vEnd; ++v) { 6786 const PetscInt newp = vStartNew + (v - vStart); 6787 const PetscInt *support, *cone; 6788 PetscInt size, s; 6789 6790 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6791 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6792 for (s = 0; s < size; ++s) { 6793 if (support[s] >= fMax) { 6794 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6795 } else { 6796 PetscInt r = 0; 6797 6798 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6799 if (cone[1] == v) r = 1; 6800 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6801 } 6802 } 6803 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6804 #if 1 6805 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6806 for (p = 0; p < size; ++p) { 6807 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6808 } 6809 #endif 6810 } 6811 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6812 for (f = fStart; f < fMax; ++f) { 6813 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6814 const PetscInt *cone, *support; 6815 PetscInt size, newSize = 2, s; 6816 6817 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6818 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6819 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6820 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6821 for (s = 0; s < size; ++s) { 6822 PetscInt r = 0; 6823 6824 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6825 if (support[s] >= cMax) { 6826 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6827 newSize += 1; 6828 } else { 6829 if (cone[1] == f) r = 1; 6830 else if (cone[2] == f) r = 2; 6831 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6832 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6833 newSize += 2; 6834 } 6835 } 6836 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6837 #if 1 6838 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6839 for (p = 0; p < newSize; ++p) { 6840 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6841 } 6842 #endif 6843 } 6844 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6845 break; 6846 default: 6847 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6848 } 6849 PetscFunctionReturn(0); 6850 } 6851 6852 #undef __FUNCT__ 6853 #define __FUNCT__ "CellRefinerSetCoordinates" 6854 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6855 { 6856 PetscSection coordSection, coordSectionNew; 6857 Vec coordinates, coordinatesNew; 6858 PetscScalar *coords, *coordsNew; 6859 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6860 PetscErrorCode ierr; 6861 6862 PetscFunctionBegin; 6863 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6864 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6865 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6866 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6867 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6868 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6869 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6870 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6871 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6872 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6873 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6874 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6875 if (fMax < 0) fMax = fEnd; 6876 switch (refiner) { 6877 case 1: 6878 case 2: 6879 case 3: 6880 /* Simplicial and Hex 2D */ 6881 /* All vertices have the dim coordinates */ 6882 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6883 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6884 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6885 } 6886 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6887 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6888 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6889 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6890 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6891 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6892 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6893 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6894 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6895 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6896 /* Old vertices have the same coordinates */ 6897 for (v = vStart; v < vEnd; ++v) { 6898 const PetscInt newv = vStartNew + (v - vStart); 6899 PetscInt off, offnew, d; 6900 6901 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6902 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6903 for (d = 0; d < dim; ++d) { 6904 coordsNew[offnew+d] = coords[off+d]; 6905 } 6906 } 6907 /* Face vertices have the average of endpoint coordinates */ 6908 for (f = fStart; f < fMax; ++f) { 6909 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6910 const PetscInt *cone; 6911 PetscInt coneSize, offA, offB, offnew, d; 6912 6913 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6914 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6915 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6916 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6917 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6918 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6919 for (d = 0; d < dim; ++d) { 6920 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6921 } 6922 } 6923 /* Just Hex 2D */ 6924 if (refiner == 2) { 6925 /* Cell vertices have the average of corner coordinates */ 6926 for (c = cStart; c < cEnd; ++c) { 6927 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6928 PetscInt *cone = PETSC_NULL; 6929 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6930 6931 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6932 for (p = 0; p < closureSize*2; p += 2) { 6933 const PetscInt point = cone[p]; 6934 if ((point >= vStart) && (point < vEnd)) { 6935 cone[coneSize++] = point; 6936 } 6937 } 6938 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6939 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6940 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6941 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6942 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6943 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6944 for (d = 0; d < dim; ++d) { 6945 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6946 } 6947 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6948 } 6949 } 6950 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6951 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6952 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6953 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6954 break; 6955 default: 6956 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6957 } 6958 PetscFunctionReturn(0); 6959 } 6960 6961 #undef __FUNCT__ 6962 #define __FUNCT__ "DMPlexCreateProcessSF" 6963 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6964 { 6965 PetscInt numRoots, numLeaves, l; 6966 const PetscInt *localPoints; 6967 const PetscSFNode *remotePoints; 6968 PetscInt *localPointsNew; 6969 PetscSFNode *remotePointsNew; 6970 PetscInt *ranks, *ranksNew; 6971 PetscErrorCode ierr; 6972 6973 PetscFunctionBegin; 6974 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6975 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6976 for (l = 0; l < numLeaves; ++l) { 6977 ranks[l] = remotePoints[l].rank; 6978 } 6979 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6980 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6981 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6982 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6983 for (l = 0; l < numLeaves; ++l) { 6984 ranksNew[l] = ranks[l]; 6985 localPointsNew[l] = l; 6986 remotePointsNew[l].index = 0; 6987 remotePointsNew[l].rank = ranksNew[l]; 6988 } 6989 ierr = PetscFree(ranks);CHKERRQ(ierr); 6990 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6991 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6992 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6993 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6994 PetscFunctionReturn(0); 6995 } 6996 6997 #undef __FUNCT__ 6998 #define __FUNCT__ "CellRefinerCreateSF" 6999 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7000 { 7001 PetscSF sf, sfNew, sfProcess; 7002 IS processRanks; 7003 MPI_Datatype depthType; 7004 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7005 const PetscInt *localPoints, *neighbors; 7006 const PetscSFNode *remotePoints; 7007 PetscInt *localPointsNew; 7008 PetscSFNode *remotePointsNew; 7009 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7010 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7011 PetscErrorCode ierr; 7012 7013 PetscFunctionBegin; 7014 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7015 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7016 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7017 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7018 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7019 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7020 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7021 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7022 switch (refiner) { 7023 case 3: 7024 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7025 cMax = PetscMin(cEnd, cMax); 7026 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7027 fMax = PetscMin(fEnd, fMax); 7028 } 7029 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7030 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7031 /* Caculate size of new SF */ 7032 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7033 if (numRoots < 0) PetscFunctionReturn(0); 7034 for (l = 0; l < numLeaves; ++l) { 7035 const PetscInt p = localPoints[l]; 7036 7037 switch (refiner) { 7038 case 1: 7039 /* Simplicial 2D */ 7040 if ((p >= vStart) && (p < vEnd)) { 7041 /* Old vertices stay the same */ 7042 ++numLeavesNew; 7043 } else if ((p >= fStart) && (p < fEnd)) { 7044 /* Old faces add new faces and vertex */ 7045 numLeavesNew += 1 + 2; 7046 } else if ((p >= cStart) && (p < cEnd)) { 7047 /* Old cells add new cells and interior faces */ 7048 numLeavesNew += 4 + 3; 7049 } 7050 break; 7051 case 2: 7052 /* Hex 2D */ 7053 if ((p >= vStart) && (p < vEnd)) { 7054 /* Old vertices stay the same */ 7055 ++numLeavesNew; 7056 } else if ((p >= fStart) && (p < fEnd)) { 7057 /* Old faces add new faces and vertex */ 7058 numLeavesNew += 1 + 2; 7059 } else if ((p >= cStart) && (p < cEnd)) { 7060 /* Old cells add new cells and interior faces */ 7061 numLeavesNew += 4 + 4; 7062 } 7063 break; 7064 default: 7065 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7066 } 7067 } 7068 /* Communicate depthSizes for each remote rank */ 7069 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7070 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7071 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7072 ierr = PetscMalloc7(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthMaxOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr); 7073 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7074 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7075 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7076 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7077 for (n = 0; n < numNeighbors; ++n) { 7078 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7079 } 7080 depthSizeOld[depth] = cMax; 7081 depthSizeOld[0] = vMax; 7082 depthSizeOld[depth-1] = fMax; 7083 depthSizeOld[1] = eMax; 7084 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7085 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7086 depthSizeOld[depth] = cEnd - cStart; 7087 depthSizeOld[0] = vEnd - vStart; 7088 depthSizeOld[depth-1] = fEnd - fStart; 7089 depthSizeOld[1] = eEnd - eStart; 7090 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7091 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7092 for (n = 0; n < numNeighbors; ++n) { 7093 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7094 } 7095 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7096 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7097 /* Calculate new point SF */ 7098 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7099 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7100 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7101 for (l = 0, m = 0; l < numLeaves; ++l) { 7102 PetscInt p = localPoints[l]; 7103 PetscInt rp = remotePoints[l].index, n; 7104 PetscMPIInt rrank = remotePoints[l].rank; 7105 7106 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7107 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7108 switch (refiner) { 7109 case 1: 7110 /* Simplicial 2D */ 7111 if ((p >= vStart) && (p < vEnd)) { 7112 /* Old vertices stay the same */ 7113 localPointsNew[m] = vStartNew + (p - vStart); 7114 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7115 remotePointsNew[m].rank = rrank; 7116 ++m; 7117 } else if ((p >= fStart) && (p < fEnd)) { 7118 /* Old faces add new faces and vertex */ 7119 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7120 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7121 remotePointsNew[m].rank = rrank; 7122 ++m; 7123 for (r = 0; r < 2; ++r, ++m) { 7124 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7125 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7126 remotePointsNew[m].rank = rrank; 7127 } 7128 } else if ((p >= cStart) && (p < cEnd)) { 7129 /* Old cells add new cells and interior faces */ 7130 for (r = 0; r < 4; ++r, ++m) { 7131 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7132 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7133 remotePointsNew[m].rank = rrank; 7134 } 7135 for (r = 0; r < 3; ++r, ++m) { 7136 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7137 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7138 remotePointsNew[m].rank = rrank; 7139 } 7140 } 7141 break; 7142 case 2: 7143 /* Hex 2D */ 7144 if ((p >= vStart) && (p < vEnd)) { 7145 /* Old vertices stay the same */ 7146 localPointsNew[m] = vStartNew + (p - vStart); 7147 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7148 remotePointsNew[m].rank = rrank; 7149 ++m; 7150 } else if ((p >= fStart) && (p < fEnd)) { 7151 /* Old faces add new faces and vertex */ 7152 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7153 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7154 remotePointsNew[m].rank = rrank; 7155 ++m; 7156 for (r = 0; r < 2; ++r, ++m) { 7157 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7158 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7159 remotePointsNew[m].rank = rrank; 7160 } 7161 } else if ((p >= cStart) && (p < cEnd)) { 7162 /* Old cells add new cells and interior faces */ 7163 for (r = 0; r < 4; ++r, ++m) { 7164 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7165 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7166 remotePointsNew[m].rank = rrank; 7167 } 7168 for (r = 0; r < 4; ++r, ++m) { 7169 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7170 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7171 remotePointsNew[m].rank = rrank; 7172 } 7173 } 7174 break; 7175 case 3: 7176 /* Hybrid simplicial 2D */ 7177 if ((p >= vStart) && (p < vEnd)) { 7178 /* Old vertices stay the same */ 7179 localPointsNew[m] = vStartNew + (p - vStart); 7180 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7181 remotePointsNew[m].rank = rrank; 7182 ++m; 7183 } else if ((p >= fStart) && (p < fMax)) { 7184 /* Old interior faces add new faces and vertex */ 7185 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7186 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7187 remotePointsNew[m].rank = rrank; 7188 ++m; 7189 for (r = 0; r < 2; ++r, ++m) { 7190 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7191 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7192 remotePointsNew[m].rank = rrank; 7193 } 7194 } else if ((p >= fMax) && (p < fEnd)) { 7195 /* Old hybrid faces stay the same */ 7196 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7197 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7198 remotePointsNew[m].rank = rrank; 7199 ++m; 7200 } else if ((p >= cStart) && (p < cMax)) { 7201 /* Old interior cells add new cells and interior faces */ 7202 for (r = 0; r < 4; ++r, ++m) { 7203 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7204 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7205 remotePointsNew[m].rank = rrank; 7206 } 7207 for (r = 0; r < 3; ++r, ++m) { 7208 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7209 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7210 remotePointsNew[m].rank = rrank; 7211 } 7212 } else if ((p >= cStart) && (p < cMax)) { 7213 /* Old hybrid cells add new cells and hybrid face */ 7214 for (r = 0; r < 2; ++r, ++m) { 7215 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7216 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7217 remotePointsNew[m].rank = rrank; 7218 } 7219 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7220 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth]); 7221 remotePointsNew[m].rank = rrank; 7222 ++m; 7223 } 7224 break; 7225 default: 7226 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7227 } 7228 } 7229 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7230 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7231 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7232 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7233 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7234 PetscFunctionReturn(0); 7235 } 7236 7237 #undef __FUNCT__ 7238 #define __FUNCT__ "CellRefinerCreateLabels" 7239 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7240 { 7241 PetscInt numLabels, l; 7242 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7243 PetscErrorCode ierr; 7244 7245 PetscFunctionBegin; 7246 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7247 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7248 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7249 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7250 cStartNew = 0; 7251 vStartNew = depthSize[2]; 7252 fStartNew = depthSize[2] + depthSize[0]; 7253 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7254 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7255 switch (refiner) { 7256 case 3: 7257 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7258 cMax = PetscMin(cEnd, cMax); 7259 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7260 fMax = PetscMin(fEnd, fMax); 7261 } 7262 for (l = 0; l < numLabels; ++l) { 7263 DMLabel label, labelNew; 7264 const char *lname; 7265 PetscBool isDepth; 7266 IS valueIS; 7267 const PetscInt *values; 7268 PetscInt numValues, val; 7269 7270 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7271 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7272 if (isDepth) continue; 7273 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7274 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7275 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7276 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7277 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7278 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7279 for (val = 0; val < numValues; ++val) { 7280 IS pointIS; 7281 const PetscInt *points; 7282 PetscInt numPoints, n; 7283 7284 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7285 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7286 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7287 for (n = 0; n < numPoints; ++n) { 7288 const PetscInt p = points[n]; 7289 switch (refiner) { 7290 case 1: 7291 /* Simplicial 2D */ 7292 if ((p >= vStart) && (p < vEnd)) { 7293 /* Old vertices stay the same */ 7294 newp = vStartNew + (p - vStart); 7295 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7296 } else if ((p >= fStart) && (p < fEnd)) { 7297 /* Old faces add new faces and vertex */ 7298 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7299 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7300 for (r = 0; r < 2; ++r) { 7301 newp = fStartNew + (p - fStart)*2 + r; 7302 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7303 } 7304 } else if ((p >= cStart) && (p < cEnd)) { 7305 /* Old cells add new cells and interior faces */ 7306 for (r = 0; r < 4; ++r) { 7307 newp = cStartNew + (p - cStart)*4 + r; 7308 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7309 } 7310 for (r = 0; r < 3; ++r) { 7311 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7312 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7313 } 7314 } 7315 break; 7316 case 2: 7317 /* Hex 2D */ 7318 if ((p >= vStart) && (p < vEnd)) { 7319 /* Old vertices stay the same */ 7320 newp = vStartNew + (p - vStart); 7321 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7322 } else if ((p >= fStart) && (p < fEnd)) { 7323 /* Old faces add new faces and vertex */ 7324 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7325 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7326 for (r = 0; r < 2; ++r) { 7327 newp = fStartNew + (p - fStart)*2 + r; 7328 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7329 } 7330 } else if ((p >= cStart) && (p < cEnd)) { 7331 /* Old cells add new cells and interior faces and vertex */ 7332 for (r = 0; r < 4; ++r) { 7333 newp = cStartNew + (p - cStart)*4 + r; 7334 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7335 } 7336 for (r = 0; r < 4; ++r) { 7337 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7338 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7339 } 7340 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7341 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7342 } 7343 break; 7344 case 3: 7345 /* Hybrid simplicial 2D */ 7346 if ((p >= vStart) && (p < vEnd)) { 7347 /* Old vertices stay the same */ 7348 newp = vStartNew + (p - vStart); 7349 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7350 } else if ((p >= fStart) && (p < fMax)) { 7351 /* Old interior faces add new faces and vertex */ 7352 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7353 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7354 for (r = 0; r < 2; ++r) { 7355 newp = fStartNew + (p - fStart)*2 + r; 7356 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7357 } 7358 } else if ((p >= fMax) && (p < fEnd)) { 7359 /* Old hybrid faces stay the same */ 7360 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7361 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7362 } else if ((p >= cStart) && (p < cMax)) { 7363 /* Old interior cells add new cells and interior faces */ 7364 for (r = 0; r < 4; ++r) { 7365 newp = cStartNew + (p - cStart)*4 + r; 7366 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7367 } 7368 for (r = 0; r < 3; ++r) { 7369 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7370 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7371 } 7372 } else if ((p >= cMax) && (p < cEnd)) { 7373 /* Old hybrid cells add new cells and hybrid face */ 7374 for (r = 0; r < 2; ++r) { 7375 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7376 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7377 } 7378 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7379 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7380 } 7381 break; 7382 default: 7383 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7384 } 7385 } 7386 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7387 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7388 } 7389 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7390 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7391 if (0) { 7392 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7393 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7394 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7395 } 7396 } 7397 PetscFunctionReturn(0); 7398 } 7399 7400 #undef __FUNCT__ 7401 #define __FUNCT__ "DMPlexRefine_Uniform" 7402 /* This will only work for interpolated meshes */ 7403 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7404 { 7405 DM rdm; 7406 PetscInt *depthSize; 7407 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7408 PetscErrorCode ierr; 7409 7410 PetscFunctionBegin; 7411 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7412 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7413 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7414 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7415 /* Calculate number of new points of each depth */ 7416 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7417 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7418 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7419 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7420 /* Step 1: Set chart */ 7421 for (d = 0; d <= depth; ++d) { 7422 pEnd += depthSize[d]; 7423 } 7424 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7425 /* Step 2: Set cone/support sizes */ 7426 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7427 /* Step 3: Setup refined DM */ 7428 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7429 /* Step 4: Set cones and supports */ 7430 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7431 /* Step 5: Stratify */ 7432 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7433 /* Step 6: Set coordinates for vertices */ 7434 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7435 /* Step 7: Create pointSF */ 7436 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7437 /* Step 8: Create labels */ 7438 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7439 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7440 7441 *dmRefined = rdm; 7442 #if 0 7443 DM_Plex *mesh = (DM_Plex *) dm->data; 7444 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 7445 /* ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); */ 7446 7447 PetscFunctionBegin; 7448 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7449 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 7450 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7451 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7452 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 7453 7454 /* Count number of new cells which are normal and extra */ 7455 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 7456 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 7457 for (c = cStart; c < cEnd2; ++c) { 7458 PetscInt n; 7459 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7460 newNumCellsNormal += n; 7461 } 7462 for (c = cEnd2; c < cEnd; ++c) { 7463 PetscInt n; 7464 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7465 newNumCellsExtra += n; 7466 } 7467 newNumCells = newNumCellsNormal + newNumCellsExtra; 7468 /* Count number of new vertices which are normal and extra */ 7469 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 7470 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 7471 for (c = cStart; c < cEnd; ++c) { 7472 PetscInt *closure = PETSC_NULL; 7473 PetscInt closureSize, numCorners = 0, p; 7474 7475 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7476 for (p = 0; p < closureSize*2; p += 2) { 7477 const PetscInt point = closure[p]; 7478 if ((point >= vStart) && (point < vEnd)) { 7479 closure[numCorners++] = point; 7480 } 7481 } 7482 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCell */ 7483 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7484 } 7485 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 7486 for (c = cEnd2; c < cEnd; ++c) { 7487 PetscInt *closure = PETSC_NULL; 7488 PetscInt closureSize, numCorners = 0, p; 7489 7490 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7491 for (p = 0; p < closureSize*2; p += 2) { 7492 const PetscInt point = closure[p]; 7493 if ((point >= vStart) && (point < vEnd)) { 7494 closure[numCorners++] = point; 7495 } 7496 } 7497 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCellUncensored */ 7498 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7499 } /* for */ 7500 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 7501 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 7502 7503 #if 1 7504 PetscInt oldNumCellsNormal = cEnd2 - cStart; 7505 PetscInt oldNumCellsExtra = cEnd - cEnd2; 7506 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 7507 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 7508 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 7509 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 7510 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 7511 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 7512 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 7513 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 7514 ierr = PetscSynchronizedFlush(comm); 7515 #endif 7516 7517 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 7518 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 7519 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 7520 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 7521 ierr = DMPlexGetHybridBounds(*dmRefined, newNumCellsNormal, PETSC_NULL, PETSC_NULL, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 7522 /* Set cone and support sizes for new normal cells */ 7523 PetscInt newCell = 0; 7524 for (c = cStart; c < cEnd2; ++c) { 7525 PetscInt coneSize, n, i; 7526 7527 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7528 ierr = CellRefinerGetNumSubcells(refiner, c, &n); /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7529 for (i = 0; i < n; ++i, ++newCell) { 7530 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 7531 } 7532 7533 PetscInt *closure = PETSC_NULL; 7534 PetscInt closureSize, numCorners = 0, p; 7535 7536 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7537 for (p = 0; p < closureSize*2; p += 2) { 7538 const PetscInt point = closure[p]; 7539 if ((point >= vStart) && (point < vEnd)) { 7540 closure[numCorners++] = point; 7541 } 7542 } 7543 /* ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); */ /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7544 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7545 } 7546 7547 /* Reset current new cell value and loop over censored cells. */ 7548 curNewCell = _orderNewMesh->cellsCensored().min(); 7549 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7550 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7551 /* Set new cone and support sizes */ 7552 cV.clear(); 7553 sieve->cone(*c_iter, cV); 7554 const point_type* cone = cV.getPoints(); 7555 const int coneSize = cV.getSize(); 7556 7557 const point_type* newCells; 7558 int numNewCells = 0; 7559 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7560 7561 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7562 newSieve->setConeSize(curNewCell, coneSize); 7563 for (int iVertex=0; iVertex < coneSize; ++iVertex) { 7564 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 7565 } /* for */ 7566 } /* for */ 7567 } /* for */ 7568 newSieve->allocate(); 7569 7570 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 7571 7572 /* Create refined cells in new sieve. */ 7573 curNewCell = _orderNewMesh->cellsNormal().min(); 7574 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 7575 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 7576 cV.clear(); 7577 sieve->cone(*c_iter, cV); 7578 const point_type *cone = cV.getPoints(); 7579 const int coneSize = cV.getSize(); 7580 7581 const point_type* newCells; 7582 int numNewCells = 0; 7583 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7584 7585 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7586 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7587 } /* for */ 7588 } /* for */ 7589 curNewCell = _orderNewMesh->cellsCensored().min(); 7590 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7591 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7592 cV.clear(); 7593 sieve->cone(*c_iter, cV); 7594 const point_type *cone = cV.getPoints(); 7595 const int coneSize = cV.getSize(); 7596 7597 const point_type* newCells; 7598 int numNewCells = 0; 7599 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7600 7601 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7602 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7603 } /* for */ 7604 } /* for */ 7605 newSieve->symmetrize(); 7606 7607 /* Set coordinates in refined mesh. */ 7608 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 7609 assert(!coordinates.isNull()); 7610 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 7611 assert(!newCoordinates.isNull()); 7612 7613 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 7614 assert(vertices->size() > 0); 7615 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 7616 assert(spaceDim > 0); 7617 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 7618 7619 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 7620 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 7621 newCoordinates->setFiberDimension(*v_iter, spaceDim); 7622 } /* for */ 7623 newCoordinates->allocatePoint(); 7624 7625 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 7626 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7627 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7628 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7629 } /* for */ 7630 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 7631 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7632 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7633 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7634 } /* for */ 7635 7636 refiner.setCoordsNewVertices(newCoordinates, coordinates); 7637 7638 /* Create sensored depth */ 7639 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 7640 assert(!censoredLabel.isNull()); 7641 7642 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 7643 7644 newSieve->roots(depthVisitor); 7645 while (depthVisitor.isModified()) { 7646 /* FIX: Avoid the copy here somehow by fixing the traversal */ 7647 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 7648 7649 depthVisitor.clear(); 7650 newSieve->support(modifiedPoints, depthVisitor); 7651 } /* while */ 7652 /* Stratify refined mesh */ 7653 /* Calculate new point SF */ 7654 _calcNewOverlap(newMesh, mesh, refiner); 7655 /* Calculate new labels */ 7656 _createLabels(newMesh, mesh, refiner); 7657 #endif 7658 PetscFunctionReturn(0); 7659 } 7660 7661 #undef __FUNCT__ 7662 #define __FUNCT__ "DMPlexSetRefinementUniform" 7663 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7664 { 7665 DM_Plex *mesh = (DM_Plex *) dm->data; 7666 7667 PetscFunctionBegin; 7668 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7669 mesh->refinementUniform = refinementUniform; 7670 PetscFunctionReturn(0); 7671 } 7672 7673 #undef __FUNCT__ 7674 #define __FUNCT__ "DMPlexGetRefinementUniform" 7675 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7676 { 7677 DM_Plex *mesh = (DM_Plex *) dm->data; 7678 7679 PetscFunctionBegin; 7680 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7681 PetscValidPointer(refinementUniform, 2); 7682 *refinementUniform = mesh->refinementUniform; 7683 PetscFunctionReturn(0); 7684 } 7685 7686 #undef __FUNCT__ 7687 #define __FUNCT__ "DMPlexSetRefinementLimit" 7688 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7689 { 7690 DM_Plex *mesh = (DM_Plex *) dm->data; 7691 7692 PetscFunctionBegin; 7693 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7694 mesh->refinementLimit = refinementLimit; 7695 PetscFunctionReturn(0); 7696 } 7697 7698 #undef __FUNCT__ 7699 #define __FUNCT__ "DMPlexGetRefinementLimit" 7700 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7701 { 7702 DM_Plex *mesh = (DM_Plex *) dm->data; 7703 7704 PetscFunctionBegin; 7705 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7706 PetscValidPointer(refinementLimit, 2); 7707 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7708 *refinementLimit = mesh->refinementLimit; 7709 PetscFunctionReturn(0); 7710 } 7711 7712 #undef __FUNCT__ 7713 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7714 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7715 { 7716 PetscInt dim, cStart, coneSize, cMax; 7717 PetscErrorCode ierr; 7718 7719 PetscFunctionBegin; 7720 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7721 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7722 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7723 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7724 switch (dim) { 7725 case 2: 7726 switch (coneSize) { 7727 case 3: 7728 if (cMax >= 0) { 7729 *cellRefiner = 3; /* Hybrid */ 7730 } else { 7731 *cellRefiner = 1; /* Triangular */ 7732 } 7733 break; 7734 case 4: 7735 if (cMax >= 0) { 7736 *cellRefiner = 4; /* Hybrid */ 7737 } else { 7738 *cellRefiner = 2; /* Quadrilateral */ 7739 } 7740 break; 7741 default: 7742 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7743 } 7744 break; 7745 default: 7746 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7747 } 7748 PetscFunctionReturn(0); 7749 } 7750 7751 #undef __FUNCT__ 7752 #define __FUNCT__ "DMRefine_Plex" 7753 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7754 { 7755 PetscReal refinementLimit; 7756 PetscInt dim, cStart, cEnd; 7757 char genname[1024], *name = PETSC_NULL; 7758 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7759 PetscErrorCode ierr; 7760 7761 PetscFunctionBegin; 7762 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7763 if (isUniform) { 7764 CellRefiner cellRefiner; 7765 7766 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7767 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7768 PetscFunctionReturn(0); 7769 } 7770 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7771 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7772 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7773 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7774 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7775 if (flg) {name = genname;} 7776 if (name) { 7777 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7778 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7779 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7780 } 7781 switch (dim) { 7782 case 2: 7783 if (!name || isTriangle) { 7784 #if defined(PETSC_HAVE_TRIANGLE) 7785 double *maxVolumes; 7786 PetscInt c; 7787 7788 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7789 for (c = 0; c < cEnd-cStart; ++c) { 7790 maxVolumes[c] = refinementLimit; 7791 } 7792 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7793 #else 7794 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7795 #endif 7796 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7797 break; 7798 case 3: 7799 if (!name || isCTetgen) { 7800 #if defined(PETSC_HAVE_CTETGEN) 7801 PetscReal *maxVolumes; 7802 PetscInt c; 7803 7804 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7805 for (c = 0; c < cEnd-cStart; ++c) { 7806 maxVolumes[c] = refinementLimit; 7807 } 7808 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7809 #else 7810 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7811 #endif 7812 } else if (isTetgen) { 7813 #if defined(PETSC_HAVE_TETGEN) 7814 double *maxVolumes; 7815 PetscInt c; 7816 7817 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7818 for (c = 0; c < cEnd-cStart; ++c) { 7819 maxVolumes[c] = refinementLimit; 7820 } 7821 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7822 #else 7823 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7824 #endif 7825 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7826 break; 7827 default: 7828 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7829 } 7830 PetscFunctionReturn(0); 7831 } 7832 7833 #undef __FUNCT__ 7834 #define __FUNCT__ "DMPlexGetDepth" 7835 /*@ 7836 DMPlexGetDepth - get the number of strata 7837 7838 Not Collective 7839 7840 Input Parameters: 7841 . dm - The DMPlex object 7842 7843 Output Parameters: 7844 . depth - number of strata 7845 7846 Level: developer 7847 7848 Notes: 7849 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7850 7851 .keywords: mesh, points 7852 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7853 @*/ 7854 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7855 { 7856 PetscInt d; 7857 PetscErrorCode ierr; 7858 7859 PetscFunctionBegin; 7860 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7861 PetscValidPointer(depth, 2); 7862 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7863 *depth = d-1; 7864 PetscFunctionReturn(0); 7865 } 7866 7867 #undef __FUNCT__ 7868 #define __FUNCT__ "DMPlexGetDepthStratum" 7869 /*@ 7870 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7871 7872 Not Collective 7873 7874 Input Parameters: 7875 + dm - The DMPlex object 7876 - stratumValue - The requested depth 7877 7878 Output Parameters: 7879 + start - The first point at this depth 7880 - end - One beyond the last point at this depth 7881 7882 Level: developer 7883 7884 .keywords: mesh, points 7885 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7886 @*/ 7887 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7888 { 7889 DM_Plex *mesh = (DM_Plex *) dm->data; 7890 DMLabel next = mesh->labels; 7891 PetscBool flg = PETSC_FALSE; 7892 PetscInt depth; 7893 PetscErrorCode ierr; 7894 7895 PetscFunctionBegin; 7896 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7897 if (stratumValue < 0) { 7898 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7899 PetscFunctionReturn(0); 7900 } else { 7901 PetscInt pStart, pEnd; 7902 7903 if (start) {*start = 0;} 7904 if (end) {*end = 0;} 7905 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7906 if (pStart == pEnd) {PetscFunctionReturn(0);} 7907 } 7908 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7909 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7910 /* We should have a generic GetLabel() and a Label class */ 7911 while (next) { 7912 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7913 if (flg) break; 7914 next = next->next; 7915 } 7916 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7917 depth = stratumValue; 7918 if ((depth < 0) || (depth >= next->numStrata)) { 7919 if (start) {*start = 0;} 7920 if (end) {*end = 0;} 7921 } else { 7922 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7923 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7924 } 7925 PetscFunctionReturn(0); 7926 } 7927 7928 #undef __FUNCT__ 7929 #define __FUNCT__ "DMPlexGetHeightStratum" 7930 /*@ 7931 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7932 7933 Not Collective 7934 7935 Input Parameters: 7936 + dm - The DMPlex object 7937 - stratumValue - The requested height 7938 7939 Output Parameters: 7940 + start - The first point at this height 7941 - end - One beyond the last point at this height 7942 7943 Level: developer 7944 7945 .keywords: mesh, points 7946 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7947 @*/ 7948 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7949 { 7950 DM_Plex *mesh = (DM_Plex *) dm->data; 7951 DMLabel next = mesh->labels; 7952 PetscBool flg = PETSC_FALSE; 7953 PetscInt depth; 7954 PetscErrorCode ierr; 7955 7956 PetscFunctionBegin; 7957 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7958 if (stratumValue < 0) { 7959 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7960 } else { 7961 PetscInt pStart, pEnd; 7962 7963 if (start) {*start = 0;} 7964 if (end) {*end = 0;} 7965 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7966 if (pStart == pEnd) {PetscFunctionReturn(0);} 7967 } 7968 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7969 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7970 /* We should have a generic GetLabel() and a Label class */ 7971 while (next) { 7972 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7973 if (flg) break; 7974 next = next->next; 7975 } 7976 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7977 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7978 if ((depth < 0) || (depth >= next->numStrata)) { 7979 if (start) {*start = 0;} 7980 if (end) {*end = 0;} 7981 } else { 7982 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7983 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7984 } 7985 PetscFunctionReturn(0); 7986 } 7987 7988 #undef __FUNCT__ 7989 #define __FUNCT__ "DMPlexCreateSectionInitial" 7990 /* Set the number of dof on each point and separate by fields */ 7991 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7992 { 7993 PetscInt *numDofTot; 7994 PetscInt pStart = 0, pEnd = 0; 7995 PetscInt p, d, f; 7996 PetscErrorCode ierr; 7997 7998 PetscFunctionBegin; 7999 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 8000 for (d = 0; d <= dim; ++d) { 8001 numDofTot[d] = 0; 8002 for (f = 0; f < numFields; ++f) { 8003 numDofTot[d] += numDof[f*(dim+1)+d]; 8004 } 8005 } 8006 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 8007 if (numFields > 0) { 8008 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 8009 if (numComp) { 8010 for (f = 0; f < numFields; ++f) { 8011 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 8012 } 8013 } 8014 } 8015 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8016 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 8017 for (d = 0; d <= dim; ++d) { 8018 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 8019 for (p = pStart; p < pEnd; ++p) { 8020 for (f = 0; f < numFields; ++f) { 8021 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 8022 } 8023 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 8024 } 8025 } 8026 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 8027 PetscFunctionReturn(0); 8028 } 8029 8030 #undef __FUNCT__ 8031 #define __FUNCT__ "DMPlexCreateSectionBCDof" 8032 /* Set the number of dof on each point and separate by fields 8033 If constDof is PETSC_DETERMINE, constrain every dof on the point 8034 */ 8035 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 8036 { 8037 PetscInt numFields; 8038 PetscInt bc; 8039 PetscErrorCode ierr; 8040 8041 PetscFunctionBegin; 8042 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8043 for (bc = 0; bc < numBC; ++bc) { 8044 PetscInt field = 0; 8045 const PetscInt *idx; 8046 PetscInt n, i; 8047 8048 if (numFields) {field = bcField[bc];} 8049 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 8050 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 8051 for (i = 0; i < n; ++i) { 8052 const PetscInt p = idx[i]; 8053 PetscInt numConst = constDof; 8054 8055 /* Constrain every dof on the point */ 8056 if (numConst < 0) { 8057 if (numFields) { 8058 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 8059 } else { 8060 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 8061 } 8062 } 8063 if (numFields) { 8064 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 8065 } 8066 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 8067 } 8068 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 8069 } 8070 PetscFunctionReturn(0); 8071 } 8072 8073 #undef __FUNCT__ 8074 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 8075 /* Set the constrained indices on each point and separate by fields */ 8076 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 8077 { 8078 PetscInt *maxConstraints; 8079 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 8080 PetscErrorCode ierr; 8081 8082 PetscFunctionBegin; 8083 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8084 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8085 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 8086 for (f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 8087 for (p = pStart; p < pEnd; ++p) { 8088 PetscInt cdof; 8089 8090 if (numFields) { 8091 for (f = 0; f < numFields; ++f) { 8092 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 8093 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 8094 } 8095 } else { 8096 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8097 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 8098 } 8099 } 8100 for (f = 0; f < numFields; ++f) { 8101 maxConstraints[numFields] += maxConstraints[f]; 8102 } 8103 if (maxConstraints[numFields]) { 8104 PetscInt *indices; 8105 8106 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8107 for (p = pStart; p < pEnd; ++p) { 8108 PetscInt cdof, d; 8109 8110 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8111 if (cdof) { 8112 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 8113 if (numFields) { 8114 PetscInt numConst = 0, foff = 0; 8115 8116 for (f = 0; f < numFields; ++f) { 8117 PetscInt cfdof, fdof; 8118 8119 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8120 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 8121 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 8122 for (d = 0; d < cfdof; ++d) { 8123 indices[numConst+d] = d; 8124 } 8125 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 8126 for (d = 0; d < cfdof; ++d) { 8127 indices[numConst+d] += foff; 8128 } 8129 numConst += cfdof; 8130 foff += fdof; 8131 } 8132 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8133 } else { 8134 for (d = 0; d < cdof; ++d) { 8135 indices[d] = d; 8136 } 8137 } 8138 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8139 } 8140 } 8141 ierr = PetscFree(indices);CHKERRQ(ierr); 8142 } 8143 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 8144 PetscFunctionReturn(0); 8145 } 8146 8147 #undef __FUNCT__ 8148 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 8149 /* Set the constrained field indices on each point */ 8150 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 8151 { 8152 const PetscInt *points, *indices; 8153 PetscInt numFields, maxDof, numPoints, p, numConstraints; 8154 PetscErrorCode ierr; 8155 8156 PetscFunctionBegin; 8157 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8158 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 8159 8160 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 8161 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 8162 if (!constraintIndices) { 8163 PetscInt *idx, i; 8164 8165 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8166 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 8167 for (i = 0; i < maxDof; ++i) {idx[i] = i;} 8168 for (p = 0; p < numPoints; ++p) { 8169 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 8170 } 8171 ierr = PetscFree(idx);CHKERRQ(ierr); 8172 } else { 8173 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 8174 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 8175 for (p = 0; p < numPoints; ++p) { 8176 PetscInt fcdof; 8177 8178 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 8179 if (fcdof != numConstraints) SETERRQ4(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints); 8180 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 8181 } 8182 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 8183 } 8184 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 8185 PetscFunctionReturn(0); 8186 } 8187 8188 #undef __FUNCT__ 8189 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 8190 /* Set the constrained indices on each point and separate by fields */ 8191 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 8192 { 8193 PetscInt *indices; 8194 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 8195 PetscErrorCode ierr; 8196 8197 PetscFunctionBegin; 8198 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8199 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8200 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8201 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 8202 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8203 for (p = pStart; p < pEnd; ++p) { 8204 PetscInt cdof, d; 8205 8206 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8207 if (cdof) { 8208 PetscInt numConst = 0, foff = 0; 8209 8210 for (f = 0; f < numFields; ++f) { 8211 const PetscInt *fcind; 8212 PetscInt fdof, fcdof; 8213 8214 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8215 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8216 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 8217 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8218 for (d = 0; d < fcdof; ++d) { 8219 indices[numConst+d] = fcind[d]+foff; 8220 } 8221 foff += fdof; 8222 numConst += fcdof; 8223 } 8224 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8225 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8226 } 8227 } 8228 ierr = PetscFree(indices);CHKERRQ(ierr); 8229 PetscFunctionReturn(0); 8230 } 8231 8232 #undef __FUNCT__ 8233 #define __FUNCT__ "DMPlexCreateSection" 8234 /*@C 8235 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8236 8237 Not Collective 8238 8239 Input Parameters: 8240 + dm - The DMPlex object 8241 . dim - The spatial dimension of the problem 8242 . numFields - The number of fields in the problem 8243 . numComp - An array of size numFields that holds the number of components for each field 8244 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8245 . numBC - The number of boundary conditions 8246 . bcField - An array of size numBC giving the field number for each boundry condition 8247 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8248 8249 Output Parameter: 8250 . section - The PetscSection object 8251 8252 Notes: numDof[f*(dim+1)+d] gives the number of dof for field f on sieve points of dimension d. For instance, numDof[1] is the 8253 nubmer of dof for field 0 on each edge. 8254 8255 Level: developer 8256 8257 .keywords: mesh, elements 8258 .seealso: DMPlexCreate(), PetscSectionCreate() 8259 @*/ 8260 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8261 { 8262 PetscErrorCode ierr; 8263 8264 PetscFunctionBegin; 8265 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8266 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8267 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8268 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8269 { 8270 PetscBool view = PETSC_FALSE; 8271 8272 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8273 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8274 } 8275 PetscFunctionReturn(0); 8276 } 8277 8278 #undef __FUNCT__ 8279 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8280 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8281 { 8282 PetscSection section; 8283 PetscErrorCode ierr; 8284 8285 PetscFunctionBegin; 8286 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8287 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8288 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8289 PetscFunctionReturn(0); 8290 } 8291 8292 #undef __FUNCT__ 8293 #define __FUNCT__ "DMPlexGetCoordinateSection" 8294 /*@ 8295 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8296 8297 Not Collective 8298 8299 Input Parameter: 8300 . dm - The DMPlex object 8301 8302 Output Parameter: 8303 . section - The PetscSection object 8304 8305 Level: intermediate 8306 8307 .keywords: mesh, coordinates 8308 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8309 @*/ 8310 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8311 { 8312 DM cdm; 8313 PetscErrorCode ierr; 8314 8315 PetscFunctionBegin; 8316 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8317 PetscValidPointer(section, 2); 8318 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8319 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8320 PetscFunctionReturn(0); 8321 } 8322 8323 #undef __FUNCT__ 8324 #define __FUNCT__ "DMPlexSetCoordinateSection" 8325 /*@ 8326 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8327 8328 Not Collective 8329 8330 Input Parameters: 8331 + dm - The DMPlex object 8332 - section - The PetscSection object 8333 8334 Level: intermediate 8335 8336 .keywords: mesh, coordinates 8337 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8338 @*/ 8339 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8340 { 8341 DM cdm; 8342 PetscErrorCode ierr; 8343 8344 PetscFunctionBegin; 8345 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8346 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8347 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8348 PetscFunctionReturn(0); 8349 } 8350 8351 #undef __FUNCT__ 8352 #define __FUNCT__ "DMPlexGetConeSection" 8353 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8354 { 8355 DM_Plex *mesh = (DM_Plex *) dm->data; 8356 8357 PetscFunctionBegin; 8358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8359 if (section) *section = mesh->coneSection; 8360 PetscFunctionReturn(0); 8361 } 8362 8363 #undef __FUNCT__ 8364 #define __FUNCT__ "DMPlexGetCones" 8365 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8366 { 8367 DM_Plex *mesh = (DM_Plex *) dm->data; 8368 8369 PetscFunctionBegin; 8370 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8371 if (cones) *cones = mesh->cones; 8372 PetscFunctionReturn(0); 8373 } 8374 8375 #undef __FUNCT__ 8376 #define __FUNCT__ "DMPlexGetConeOrientations" 8377 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8378 { 8379 DM_Plex *mesh = (DM_Plex *) dm->data; 8380 8381 PetscFunctionBegin; 8382 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8383 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8384 PetscFunctionReturn(0); 8385 } 8386 8387 #undef __FUNCT__ 8388 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8389 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8390 { 8391 const PetscInt embedDim = 2; 8392 PetscReal x = PetscRealPart(point[0]); 8393 PetscReal y = PetscRealPart(point[1]); 8394 PetscReal v0[2], J[4], invJ[4], detJ; 8395 PetscReal xi, eta; 8396 PetscErrorCode ierr; 8397 8398 PetscFunctionBegin; 8399 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8400 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8401 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8402 8403 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 8404 *cell = c; 8405 } else { 8406 *cell = -1; 8407 } 8408 PetscFunctionReturn(0); 8409 } 8410 8411 #undef __FUNCT__ 8412 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8413 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8414 { 8415 PetscSection coordSection; 8416 Vec coordsLocal; 8417 const PetscScalar *coords; 8418 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8419 PetscReal x = PetscRealPart(point[0]); 8420 PetscReal y = PetscRealPart(point[1]); 8421 PetscInt crossings = 0, f; 8422 PetscErrorCode ierr; 8423 8424 PetscFunctionBegin; 8425 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8426 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8427 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8428 for (f = 0; f < 4; ++f) { 8429 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8430 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8431 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8432 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8433 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8434 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8435 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8436 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8437 if ((cond1 || cond2) && above) ++crossings; 8438 } 8439 if (crossings % 2) { 8440 *cell = c; 8441 } else { 8442 *cell = -1; 8443 } 8444 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8445 PetscFunctionReturn(0); 8446 } 8447 8448 #undef __FUNCT__ 8449 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8450 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8451 { 8452 const PetscInt embedDim = 3; 8453 PetscReal v0[3], J[9], invJ[9], detJ; 8454 PetscReal x = PetscRealPart(point[0]); 8455 PetscReal y = PetscRealPart(point[1]); 8456 PetscReal z = PetscRealPart(point[2]); 8457 PetscReal xi, eta, zeta; 8458 PetscErrorCode ierr; 8459 8460 PetscFunctionBegin; 8461 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8462 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8463 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8464 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8465 8466 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 8467 *cell = c; 8468 } else { 8469 *cell = -1; 8470 } 8471 PetscFunctionReturn(0); 8472 } 8473 8474 #undef __FUNCT__ 8475 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8476 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8477 { 8478 PetscSection coordSection; 8479 Vec coordsLocal; 8480 const PetscScalar *coords; 8481 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8482 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8483 PetscBool found = PETSC_TRUE; 8484 PetscInt f; 8485 PetscErrorCode ierr; 8486 8487 PetscFunctionBegin; 8488 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8489 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8490 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8491 for (f = 0; f < 6; ++f) { 8492 /* Check the point is under plane */ 8493 /* Get face normal */ 8494 PetscReal v_i[3]; 8495 PetscReal v_j[3]; 8496 PetscReal normal[3]; 8497 PetscReal pp[3]; 8498 PetscReal dot; 8499 8500 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8501 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8502 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8503 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8504 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8505 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8506 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8507 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8508 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8509 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8510 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8511 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8512 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8513 8514 /* Check that projected point is in face (2D location problem) */ 8515 if (dot < 0.0) { 8516 found = PETSC_FALSE; 8517 break; 8518 } 8519 } 8520 if (found) { 8521 *cell = c; 8522 } else { 8523 *cell = -1; 8524 } 8525 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8526 PetscFunctionReturn(0); 8527 } 8528 8529 #undef __FUNCT__ 8530 #define __FUNCT__ "DMLocatePoints_Plex" 8531 /* 8532 Need to implement using the guess 8533 */ 8534 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8535 { 8536 PetscInt cell = -1/*, guess = -1*/; 8537 PetscInt bs, numPoints, p; 8538 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8539 PetscInt *cells; 8540 PetscScalar *a; 8541 PetscErrorCode ierr; 8542 8543 PetscFunctionBegin; 8544 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8545 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8546 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8547 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 8548 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8549 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8550 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8551 if (bs != dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim); 8552 numPoints /= bs; 8553 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8554 for (p = 0; p < numPoints; ++p) { 8555 const PetscScalar *point = &a[p*bs]; 8556 8557 switch (dim) { 8558 case 2: 8559 for (c = cStart; c < cEnd; ++c) { 8560 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8561 switch (coneSize) { 8562 case 3: 8563 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8564 break; 8565 case 4: 8566 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8567 break; 8568 default: 8569 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8570 } 8571 if (cell >= 0) break; 8572 } 8573 break; 8574 case 3: 8575 for (c = cStart; c < cEnd; ++c) { 8576 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8577 switch (coneSize) { 8578 case 4: 8579 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8580 break; 8581 case 8: 8582 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8583 break; 8584 default: 8585 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8586 } 8587 if (cell >= 0) break; 8588 } 8589 break; 8590 default: 8591 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8592 } 8593 cells[p] = cell; 8594 } 8595 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8596 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8597 PetscFunctionReturn(0); 8598 } 8599 8600 /******************************** FEM Support **********************************/ 8601 8602 #undef __FUNCT__ 8603 #define __FUNCT__ "DMPlexVecGetClosure" 8604 /*@C 8605 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8606 8607 Not collective 8608 8609 Input Parameters: 8610 + dm - The DM 8611 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8612 . v - The local vector 8613 - point - The sieve point in the DM 8614 8615 Output Parameters: 8616 + csize - The number of values in the closure, or PETSC_NULL 8617 - values - The array of values, which is a borrowed array and should not be freed 8618 8619 Level: intermediate 8620 8621 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8622 @*/ 8623 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8624 { 8625 PetscScalar *array, *vArray; 8626 PetscInt *points = PETSC_NULL; 8627 PetscInt offsets[32]; 8628 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8629 PetscErrorCode ierr; 8630 8631 PetscFunctionBegin; 8632 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8633 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8634 if (!section) { 8635 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8636 } 8637 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8638 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8639 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8640 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8641 /* Compress out points not in the section */ 8642 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8643 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8644 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8645 points[q*2] = points[p]; 8646 points[q*2+1] = points[p+1]; 8647 ++q; 8648 } 8649 } 8650 numPoints = q; 8651 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8652 PetscInt dof, fdof; 8653 8654 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8655 for (f = 0; f < numFields; ++f) { 8656 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8657 offsets[f+1] += fdof; 8658 } 8659 size += dof; 8660 } 8661 for (f = 1; f < numFields; ++f) { 8662 offsets[f+1] += offsets[f]; 8663 } 8664 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8665 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8666 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8667 for (p = 0; p < numPoints*2; p += 2) { 8668 PetscInt o = points[p+1]; 8669 PetscInt dof, off, d; 8670 PetscScalar *varr; 8671 8672 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8673 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8674 varr = &vArray[off]; 8675 if (numFields) { 8676 PetscInt fdof, foff, fcomp, f, c; 8677 8678 for (f = 0, foff = 0; f < numFields; ++f) { 8679 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8680 if (o >= 0) { 8681 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8682 array[offsets[f]] = varr[foff+d]; 8683 } 8684 } else { 8685 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8686 for (d = fdof/fcomp-1; d >= 0; --d) { 8687 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8688 array[offsets[f]] = varr[foff+d*fcomp+c]; 8689 } 8690 } 8691 } 8692 foff += fdof; 8693 } 8694 } else { 8695 if (o >= 0) { 8696 for (d = 0; d < dof; ++d, ++offsets[0]) { 8697 array[offsets[0]] = varr[d]; 8698 } 8699 } else { 8700 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8701 array[offsets[0]] = varr[d]; 8702 } 8703 } 8704 } 8705 } 8706 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8707 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8708 if (csize) *csize = size; 8709 *values = array; 8710 PetscFunctionReturn(0); 8711 } 8712 8713 #undef __FUNCT__ 8714 #define __FUNCT__ "DMPlexVecRestoreClosure" 8715 /*@C 8716 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8717 8718 Not collective 8719 8720 Input Parameters: 8721 + dm - The DM 8722 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8723 . v - The local vector 8724 . point - The sieve point in the DM 8725 . csize - The number of values in the closure, or PETSC_NULL 8726 - values - The array of values, which is a borrowed array and should not be freed 8727 8728 Level: intermediate 8729 8730 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8731 @*/ 8732 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8733 { 8734 PetscInt size = 0; 8735 PetscErrorCode ierr; 8736 8737 PetscFunctionBegin; 8738 /* Should work without recalculating size */ 8739 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 8740 PetscFunctionReturn(0); 8741 } 8742 8743 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8744 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8745 8746 #undef __FUNCT__ 8747 #define __FUNCT__ "updatePoint_private" 8748 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8749 { 8750 PetscInt cdof; /* The number of constraints on this point */ 8751 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8752 PetscScalar *a; 8753 PetscInt off, cind = 0, k; 8754 PetscErrorCode ierr; 8755 8756 PetscFunctionBegin; 8757 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8758 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8759 a = &array[off]; 8760 if (!cdof || setBC) { 8761 if (orientation >= 0) { 8762 for (k = 0; k < dof; ++k) { 8763 fuse(&a[k], values[k]); 8764 } 8765 } else { 8766 for (k = 0; k < dof; ++k) { 8767 fuse(&a[k], values[dof-k-1]); 8768 } 8769 } 8770 } else { 8771 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8772 if (orientation >= 0) { 8773 for (k = 0; k < dof; ++k) { 8774 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8775 fuse(&a[k], values[k]); 8776 } 8777 } else { 8778 for (k = 0; k < dof; ++k) { 8779 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8780 fuse(&a[k], values[dof-k-1]); 8781 } 8782 } 8783 } 8784 PetscFunctionReturn(0); 8785 } 8786 8787 #undef __FUNCT__ 8788 #define __FUNCT__ "updatePointFields_private" 8789 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8790 { 8791 PetscScalar *a; 8792 PetscInt numFields, off, foff, f; 8793 PetscErrorCode ierr; 8794 8795 PetscFunctionBegin; 8796 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8797 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8798 a = &array[off]; 8799 for (f = 0, foff = 0; f < numFields; ++f) { 8800 PetscInt fdof, fcomp, fcdof; 8801 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8802 PetscInt cind = 0, k, c; 8803 8804 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8805 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8806 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8807 if (!fcdof || setBC) { 8808 if (orientation >= 0) { 8809 for (k = 0; k < fdof; ++k) { 8810 fuse(&a[foff+k], values[foffs[f]+k]); 8811 } 8812 } else { 8813 for (k = fdof/fcomp-1; k >= 0; --k) { 8814 for (c = 0; c < fcomp; ++c) { 8815 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8816 } 8817 } 8818 } 8819 } else { 8820 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8821 if (orientation >= 0) { 8822 for (k = 0; k < fdof; ++k) { 8823 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8824 fuse(&a[foff+k], values[foffs[f]+k]); 8825 } 8826 } else { 8827 for (k = fdof/fcomp-1; k >= 0; --k) { 8828 for (c = 0; c < fcomp; ++c) { 8829 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8830 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8831 } 8832 } 8833 } 8834 } 8835 foff += fdof; 8836 foffs[f] += fdof; 8837 } 8838 PetscFunctionReturn(0); 8839 } 8840 8841 #undef __FUNCT__ 8842 #define __FUNCT__ "DMPlexVecSetClosure" 8843 /*@C 8844 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8845 8846 Not collective 8847 8848 Input Parameters: 8849 + dm - The DM 8850 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8851 . v - The local vector 8852 . point - The sieve point in the DM 8853 . values - The array of values, which is a borrowed array and should not be freed 8854 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8855 8856 Level: intermediate 8857 8858 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8859 @*/ 8860 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8861 { 8862 PetscScalar *array; 8863 PetscInt *points = PETSC_NULL; 8864 PetscInt offsets[32]; 8865 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8866 PetscErrorCode ierr; 8867 8868 PetscFunctionBegin; 8869 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8870 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8871 if (!section) { 8872 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8873 } 8874 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8875 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8876 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8877 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8878 /* Compress out points not in the section */ 8879 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8880 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8881 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8882 points[q*2] = points[p]; 8883 points[q*2+1] = points[p+1]; 8884 ++q; 8885 } 8886 } 8887 numPoints = q; 8888 for (p = 0; p < numPoints*2; p += 2) { 8889 PetscInt fdof; 8890 8891 for (f = 0; f < numFields; ++f) { 8892 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8893 offsets[f+1] += fdof; 8894 } 8895 } 8896 for (f = 1; f < numFields; ++f) { 8897 offsets[f+1] += offsets[f]; 8898 } 8899 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8900 if (numFields) { 8901 switch (mode) { 8902 case INSERT_VALUES: 8903 for (p = 0; p < numPoints*2; p += 2) { 8904 PetscInt o = points[p+1]; 8905 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8906 } break; 8907 case INSERT_ALL_VALUES: 8908 for (p = 0; p < numPoints*2; p += 2) { 8909 PetscInt o = points[p+1]; 8910 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8911 } break; 8912 case ADD_VALUES: 8913 for (p = 0; p < numPoints*2; p += 2) { 8914 PetscInt o = points[p+1]; 8915 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8916 } break; 8917 case ADD_ALL_VALUES: 8918 for (p = 0; p < numPoints*2; p += 2) { 8919 PetscInt o = points[p+1]; 8920 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8921 } break; 8922 default: 8923 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8924 } 8925 } else { 8926 switch (mode) { 8927 case INSERT_VALUES: 8928 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8929 PetscInt o = points[p+1]; 8930 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8931 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8932 } break; 8933 case INSERT_ALL_VALUES: 8934 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8935 PetscInt o = points[p+1]; 8936 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8937 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8938 } break; 8939 case ADD_VALUES: 8940 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8941 PetscInt o = points[p+1]; 8942 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8943 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8944 } break; 8945 case ADD_ALL_VALUES: 8946 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8947 PetscInt o = points[p+1]; 8948 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8949 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8950 } break; 8951 default: 8952 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8953 } 8954 } 8955 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8956 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8957 PetscFunctionReturn(0); 8958 } 8959 8960 #undef __FUNCT__ 8961 #define __FUNCT__ "DMPlexPrintMatSetValues" 8962 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8963 { 8964 PetscMPIInt rank; 8965 PetscInt i, j; 8966 PetscErrorCode ierr; 8967 8968 PetscFunctionBegin; 8969 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8970 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8971 for (i = 0; i < numIndices; i++) { 8972 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8973 } 8974 for (i = 0; i < numIndices; i++) { 8975 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8976 for (j = 0; j < numIndices; j++) { 8977 #if defined(PETSC_USE_COMPLEX) 8978 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8979 #else 8980 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8981 #endif 8982 } 8983 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8984 } 8985 PetscFunctionReturn(0); 8986 } 8987 8988 #undef __FUNCT__ 8989 #define __FUNCT__ "indicesPoint_private" 8990 /* . off - The global offset of this point */ 8991 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8992 { 8993 PetscInt cdof; /* The number of constraints on this point */ 8994 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8995 PetscInt cind = 0, k; 8996 PetscErrorCode ierr; 8997 8998 PetscFunctionBegin; 8999 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 9000 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 9001 if (!cdof || setBC) { 9002 if (orientation >= 0) { 9003 for (k = 0; k < dof; ++k) { 9004 indices[k] = off+k; 9005 } 9006 } else { 9007 for (k = 0; k < dof; ++k) { 9008 indices[dof-k-1] = off+k; 9009 } 9010 } 9011 } else { 9012 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 9013 if (orientation >= 0) { 9014 for (k = 0; k < dof; ++k) { 9015 if ((cind < cdof) && (k == cdofs[cind])) { 9016 /* Insert check for returning constrained indices */ 9017 indices[k] = -(off+k+1); 9018 ++cind; 9019 } else { 9020 indices[k] = off+k-cind; 9021 } 9022 } 9023 } else { 9024 for (k = 0; k < dof; ++k) { 9025 if ((cind < cdof) && (k == cdofs[cind])) { 9026 /* Insert check for returning constrained indices */ 9027 indices[dof-k-1] = -(off+k+1); 9028 ++cind; 9029 } else { 9030 indices[dof-k-1] = off+k-cind; 9031 } 9032 } 9033 } 9034 } 9035 PetscFunctionReturn(0); 9036 } 9037 9038 #undef __FUNCT__ 9039 #define __FUNCT__ "indicesPointFields_private" 9040 /* . off - The global offset of this point */ 9041 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 9042 { 9043 PetscInt numFields, foff, f; 9044 PetscErrorCode ierr; 9045 9046 PetscFunctionBegin; 9047 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9048 for (f = 0, foff = 0; f < numFields; ++f) { 9049 PetscInt fdof, fcomp, cfdof; 9050 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 9051 PetscInt cind = 0, k, c; 9052 9053 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 9054 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 9055 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 9056 if (!cfdof || setBC) { 9057 if (orientation >= 0) { 9058 for (k = 0; k < fdof; ++k) { 9059 indices[foffs[f]+k] = off+foff+k; 9060 } 9061 } else { 9062 for (k = fdof/fcomp-1; k >= 0; --k) { 9063 for (c = 0; c < fcomp; ++c) { 9064 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 9065 } 9066 } 9067 } 9068 } else { 9069 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 9070 if (orientation >= 0) { 9071 for (k = 0; k < fdof; ++k) { 9072 if ((cind < cfdof) && (k == fcdofs[cind])) { 9073 indices[foffs[f]+k] = -(off+foff+k+1); 9074 ++cind; 9075 } else { 9076 indices[foffs[f]+k] = off+foff+k-cind; 9077 } 9078 } 9079 } else { 9080 for (k = fdof/fcomp-1; k >= 0; --k) { 9081 for (c = 0; c < fcomp; ++c) { 9082 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 9083 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 9084 ++cind; 9085 } else { 9086 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 9087 } 9088 } 9089 } 9090 } 9091 } 9092 foff += fdof - cfdof; 9093 foffs[f] += fdof; 9094 } 9095 PetscFunctionReturn(0); 9096 } 9097 9098 #undef __FUNCT__ 9099 #define __FUNCT__ "DMPlexMatSetClosure" 9100 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 9101 { 9102 DM_Plex *mesh = (DM_Plex *) dm->data; 9103 PetscInt *points = PETSC_NULL; 9104 PetscInt *indices; 9105 PetscInt offsets[32]; 9106 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 9107 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 9108 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 9109 PetscErrorCode ierr; 9110 9111 PetscFunctionBegin; 9112 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9113 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 9114 if (useDefault) { 9115 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9116 } 9117 if (useGlobalDefault) { 9118 if (useDefault) { 9119 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 9120 } else { 9121 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9122 } 9123 } 9124 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9125 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 9126 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 9127 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9128 /* Compress out points not in the section */ 9129 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 9130 for (p = 0, q = 0; p < numPoints*2; p += 2) { 9131 if ((points[p] >= pStart) && (points[p] < pEnd)) { 9132 points[q*2] = points[p]; 9133 points[q*2+1] = points[p+1]; 9134 ++q; 9135 } 9136 } 9137 numPoints = q; 9138 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 9139 PetscInt fdof; 9140 9141 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 9142 for (f = 0; f < numFields; ++f) { 9143 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 9144 offsets[f+1] += fdof; 9145 } 9146 numIndices += dof; 9147 } 9148 for (f = 1; f < numFields; ++f) { 9149 offsets[f+1] += offsets[f]; 9150 } 9151 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 9152 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9153 if (numFields) { 9154 for (p = 0; p < numPoints*2; p += 2) { 9155 PetscInt o = points[p+1]; 9156 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9157 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 9158 } 9159 } else { 9160 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 9161 PetscInt o = points[p+1]; 9162 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9163 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 9164 } 9165 } 9166 if (useGlobalDefault && !useDefault) { 9167 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9168 } 9169 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 9170 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 9171 if (ierr) { 9172 PetscMPIInt rank; 9173 PetscErrorCode ierr2; 9174 9175 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 9176 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 9177 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 9178 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 9179 CHKERRQ(ierr); 9180 } 9181 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9182 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9183 PetscFunctionReturn(0); 9184 } 9185 9186 #undef __FUNCT__ 9187 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 9188 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9189 { 9190 PetscSection coordSection; 9191 Vec coordinates; 9192 const PetscScalar *coords; 9193 const PetscInt dim = 2; 9194 PetscInt d, f; 9195 PetscErrorCode ierr; 9196 9197 PetscFunctionBegin; 9198 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9199 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9200 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9201 if (v0) { 9202 for (d = 0; d < dim; d++) { 9203 v0[d] = PetscRealPart(coords[d]); 9204 } 9205 } 9206 if (J) { 9207 for (d = 0; d < dim; d++) { 9208 for (f = 0; f < dim; f++) { 9209 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9210 } 9211 } 9212 *detJ = J[0]*J[3] - J[1]*J[2]; 9213 #if 0 9214 if (detJ < 0.0) { 9215 const PetscReal xLength = mesh->periodicity[0]; 9216 9217 if (xLength != 0.0) { 9218 PetscReal v0x = coords[0*dim+0]; 9219 9220 if (v0x == 0.0) { 9221 v0x = v0[0] = xLength; 9222 } 9223 for (f = 0; f < dim; f++) { 9224 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 9225 9226 J[0*dim+f] = 0.5*(px - v0x); 9227 } 9228 } 9229 detJ = J[0]*J[3] - J[1]*J[2]; 9230 } 9231 #endif 9232 PetscLogFlops(8.0 + 3.0); 9233 } 9234 if (invJ) { 9235 const PetscReal invDet = 1.0/(*detJ); 9236 9237 invJ[0] = invDet*J[3]; 9238 invJ[1] = -invDet*J[1]; 9239 invJ[2] = -invDet*J[2]; 9240 invJ[3] = invDet*J[0]; 9241 PetscLogFlops(5.0); 9242 } 9243 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9244 PetscFunctionReturn(0); 9245 } 9246 9247 #undef __FUNCT__ 9248 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9249 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9250 { 9251 PetscSection coordSection; 9252 Vec coordinates; 9253 const PetscScalar *coords; 9254 const PetscInt dim = 2; 9255 PetscInt d, f; 9256 PetscErrorCode ierr; 9257 9258 PetscFunctionBegin; 9259 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9260 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9261 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9262 if (v0) { 9263 for (d = 0; d < dim; d++) { 9264 v0[d] = PetscRealPart(coords[d]); 9265 } 9266 } 9267 if (J) { 9268 for (d = 0; d < dim; d++) { 9269 for (f = 0; f < dim; f++) { 9270 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9271 } 9272 } 9273 *detJ = J[0]*J[3] - J[1]*J[2]; 9274 PetscLogFlops(8.0 + 3.0); 9275 } 9276 if (invJ) { 9277 const PetscReal invDet = 1.0/(*detJ); 9278 9279 invJ[0] = invDet*J[3]; 9280 invJ[1] = -invDet*J[1]; 9281 invJ[2] = -invDet*J[2]; 9282 invJ[3] = invDet*J[0]; 9283 PetscLogFlops(5.0); 9284 } 9285 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9286 PetscFunctionReturn(0); 9287 } 9288 9289 #undef __FUNCT__ 9290 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9291 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9292 { 9293 PetscSection coordSection; 9294 Vec coordinates; 9295 const PetscScalar *coords; 9296 const PetscInt dim = 3; 9297 PetscInt d, f; 9298 PetscErrorCode ierr; 9299 9300 PetscFunctionBegin; 9301 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9302 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9303 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9304 if (v0) { 9305 for (d = 0; d < dim; d++) { 9306 v0[d] = PetscRealPart(coords[d]); 9307 } 9308 } 9309 if (J) { 9310 for (d = 0; d < dim; d++) { 9311 for (f = 0; f < dim; f++) { 9312 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9313 } 9314 } 9315 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9316 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9317 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9318 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9319 PetscLogFlops(18.0 + 12.0); 9320 } 9321 if (invJ) { 9322 const PetscReal invDet = 1.0/(*detJ); 9323 9324 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9325 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9326 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9327 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9328 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9329 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9330 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9331 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9332 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9333 PetscLogFlops(37.0); 9334 } 9335 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9336 PetscFunctionReturn(0); 9337 } 9338 9339 #undef __FUNCT__ 9340 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9341 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9342 { 9343 PetscSection coordSection; 9344 Vec coordinates; 9345 const PetscScalar *coords; 9346 const PetscInt dim = 3; 9347 PetscInt d; 9348 PetscErrorCode ierr; 9349 9350 PetscFunctionBegin; 9351 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9352 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9353 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9354 if (v0) { 9355 for (d = 0; d < dim; d++) { 9356 v0[d] = PetscRealPart(coords[d]); 9357 } 9358 } 9359 if (J) { 9360 for (d = 0; d < dim; d++) { 9361 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9362 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9363 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9364 } 9365 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9366 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9367 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9368 PetscLogFlops(18.0 + 12.0); 9369 } 9370 if (invJ) { 9371 const PetscReal invDet = -1.0/(*detJ); 9372 9373 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9374 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9375 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9376 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9377 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9378 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9379 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9380 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9381 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9382 PetscLogFlops(37.0); 9383 } 9384 *detJ *= 8.0; 9385 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9386 PetscFunctionReturn(0); 9387 } 9388 9389 #undef __FUNCT__ 9390 #define __FUNCT__ "DMPlexComputeCellGeometry" 9391 /*@C 9392 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9393 9394 Collective on DM 9395 9396 Input Arguments: 9397 + dm - the DM 9398 - cell - the cell 9399 9400 Output Arguments: 9401 + v0 - the translation part of this affine transform 9402 . J - the Jacobian of the transform to the reference element 9403 . invJ - the inverse of the Jacobian 9404 - detJ - the Jacobian determinant 9405 9406 Level: advanced 9407 9408 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9409 @*/ 9410 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9411 { 9412 PetscInt dim, coneSize; 9413 PetscErrorCode ierr; 9414 9415 PetscFunctionBegin; 9416 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9417 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9418 switch (dim) { 9419 case 2: 9420 switch (coneSize) { 9421 case 3: 9422 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9423 break; 9424 case 4: 9425 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9426 break; 9427 default: 9428 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9429 } 9430 break; 9431 case 3: 9432 switch (coneSize) { 9433 case 4: 9434 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9435 break; 9436 case 8: 9437 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9438 break; 9439 default: 9440 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9441 } 9442 break; 9443 default: 9444 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9445 } 9446 PetscFunctionReturn(0); 9447 } 9448 9449 #undef __FUNCT__ 9450 #define __FUNCT__ "DMPlexGetFaceOrientation" 9451 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9452 { 9453 MPI_Comm comm = ((PetscObject) dm)->comm; 9454 PetscBool posOrient = PETSC_FALSE; 9455 const PetscInt debug = 0; 9456 PetscInt cellDim, faceSize, f; 9457 PetscErrorCode ierr; 9458 9459 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 9460 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 9461 9462 if (cellDim == numCorners-1) { 9463 /* Simplices */ 9464 faceSize = numCorners-1; 9465 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 9466 } else if (cellDim == 1 && numCorners == 3) { 9467 /* Quadratic line */ 9468 faceSize = 1; 9469 posOrient = PETSC_TRUE; 9470 } else if (cellDim == 2 && numCorners == 4) { 9471 /* Quads */ 9472 faceSize = 2; 9473 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 9474 posOrient = PETSC_TRUE; 9475 } else if ((indices[0] == 3) && (indices[1] == 0)) { 9476 posOrient = PETSC_TRUE; 9477 } else { 9478 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 9479 posOrient = PETSC_FALSE; 9480 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 9481 } 9482 } else if (cellDim == 2 && numCorners == 6) { 9483 /* Quadratic triangle (I hate this) */ 9484 /* Edges are determined by the first 2 vertices (corners of edges) */ 9485 const PetscInt faceSizeTri = 3; 9486 PetscInt sortedIndices[3], i, iFace; 9487 PetscBool found = PETSC_FALSE; 9488 PetscInt faceVerticesTriSorted[9] = { 9489 0, 3, 4, /* bottom */ 9490 1, 4, 5, /* right */ 9491 2, 3, 5, /* left */ 9492 }; 9493 PetscInt faceVerticesTri[9] = { 9494 0, 3, 4, /* bottom */ 9495 1, 4, 5, /* right */ 9496 2, 5, 3, /* left */ 9497 }; 9498 9499 faceSize = faceSizeTri; 9500 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 9501 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 9502 for (iFace = 0; iFace < 3; ++iFace) { 9503 const PetscInt ii = iFace*faceSizeTri; 9504 PetscInt fVertex, cVertex; 9505 9506 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 9507 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 9508 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 9509 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 9510 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 9511 faceVertices[fVertex] = origVertices[cVertex]; 9512 break; 9513 } 9514 } 9515 } 9516 found = PETSC_TRUE; 9517 break; 9518 } 9519 } 9520 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 9521 if (posOriented) {*posOriented = PETSC_TRUE;} 9522 PetscFunctionReturn(0); 9523 } else if (cellDim == 2 && numCorners == 9) { 9524 /* Quadratic quad (I hate this) */ 9525 /* Edges are determined by the first 2 vertices (corners of edges) */ 9526 const PetscInt faceSizeQuad = 3; 9527 PetscInt sortedIndices[3], i, iFace; 9528 PetscBool found = PETSC_FALSE; 9529 PetscInt faceVerticesQuadSorted[12] = { 9530 0, 1, 4, /* bottom */ 9531 1, 2, 5, /* right */ 9532 2, 3, 6, /* top */ 9533 0, 3, 7, /* left */ 9534 }; 9535 PetscInt faceVerticesQuad[12] = { 9536 0, 1, 4, /* bottom */ 9537 1, 2, 5, /* right */ 9538 2, 3, 6, /* top */ 9539 3, 0, 7, /* left */ 9540 }; 9541 9542 faceSize = faceSizeQuad; 9543 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 9544 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 9545 for (iFace = 0; iFace < 4; ++iFace) { 9546 const PetscInt ii = iFace*faceSizeQuad; 9547 PetscInt fVertex, cVertex; 9548 9549 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 9550 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 9551 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 9552 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 9553 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 9554 faceVertices[fVertex] = origVertices[cVertex]; 9555 break; 9556 } 9557 } 9558 } 9559 found = PETSC_TRUE; 9560 break; 9561 } 9562 } 9563 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9564 if (posOriented) {*posOriented = PETSC_TRUE;} 9565 PetscFunctionReturn(0); 9566 } else if (cellDim == 3 && numCorners == 8) { 9567 /* Hexes 9568 A hex is two oriented quads with the normal of the first 9569 pointing up at the second. 9570 9571 7---6 9572 /| /| 9573 4---5 | 9574 | 3-|-2 9575 |/ |/ 9576 0---1 9577 9578 Faces are determined by the first 4 vertices (corners of faces) */ 9579 const PetscInt faceSizeHex = 4; 9580 PetscInt sortedIndices[4], i, iFace; 9581 PetscBool found = PETSC_FALSE; 9582 PetscInt faceVerticesHexSorted[24] = { 9583 0, 1, 2, 3, /* bottom */ 9584 4, 5, 6, 7, /* top */ 9585 0, 1, 4, 5, /* front */ 9586 1, 2, 5, 6, /* right */ 9587 2, 3, 6, 7, /* back */ 9588 0, 3, 4, 7, /* left */ 9589 }; 9590 PetscInt faceVerticesHex[24] = { 9591 3, 2, 1, 0, /* bottom */ 9592 4, 5, 6, 7, /* top */ 9593 0, 1, 5, 4, /* front */ 9594 1, 2, 6, 5, /* right */ 9595 2, 3, 7, 6, /* back */ 9596 3, 0, 4, 7, /* left */ 9597 }; 9598 9599 faceSize = faceSizeHex; 9600 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9601 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9602 for (iFace = 0; iFace < 6; ++iFace) { 9603 const PetscInt ii = iFace*faceSizeHex; 9604 PetscInt fVertex, cVertex; 9605 9606 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9607 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9608 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9609 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9610 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9611 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9612 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9613 faceVertices[fVertex] = origVertices[cVertex]; 9614 break; 9615 } 9616 } 9617 } 9618 found = PETSC_TRUE; 9619 break; 9620 } 9621 } 9622 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9623 if (posOriented) {*posOriented = PETSC_TRUE;} 9624 PetscFunctionReturn(0); 9625 } else if (cellDim == 3 && numCorners == 10) { 9626 /* Quadratic tet */ 9627 /* Faces are determined by the first 3 vertices (corners of faces) */ 9628 const PetscInt faceSizeTet = 6; 9629 PetscInt sortedIndices[6], i, iFace; 9630 PetscBool found = PETSC_FALSE; 9631 PetscInt faceVerticesTetSorted[24] = { 9632 0, 1, 2, 6, 7, 8, /* bottom */ 9633 0, 3, 4, 6, 7, 9, /* front */ 9634 1, 4, 5, 7, 8, 9, /* right */ 9635 2, 3, 5, 6, 8, 9, /* left */ 9636 }; 9637 PetscInt faceVerticesTet[24] = { 9638 0, 1, 2, 6, 7, 8, /* bottom */ 9639 0, 4, 3, 6, 7, 9, /* front */ 9640 1, 5, 4, 7, 8, 9, /* right */ 9641 2, 3, 5, 8, 6, 9, /* left */ 9642 }; 9643 9644 faceSize = faceSizeTet; 9645 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9646 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9647 for (iFace=0; iFace < 4; ++iFace) { 9648 const PetscInt ii = iFace*faceSizeTet; 9649 PetscInt fVertex, cVertex; 9650 9651 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9652 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9653 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9654 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9655 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9656 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9657 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9658 faceVertices[fVertex] = origVertices[cVertex]; 9659 break; 9660 } 9661 } 9662 } 9663 found = PETSC_TRUE; 9664 break; 9665 } 9666 } 9667 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9668 if (posOriented) {*posOriented = PETSC_TRUE;} 9669 PetscFunctionReturn(0); 9670 } else if (cellDim == 3 && numCorners == 27) { 9671 /* Quadratic hexes (I hate this) 9672 A hex is two oriented quads with the normal of the first 9673 pointing up at the second. 9674 9675 7---6 9676 /| /| 9677 4---5 | 9678 | 3-|-2 9679 |/ |/ 9680 0---1 9681 9682 Faces are determined by the first 4 vertices (corners of faces) */ 9683 const PetscInt faceSizeQuadHex = 9; 9684 PetscInt sortedIndices[9], i, iFace; 9685 PetscBool found = PETSC_FALSE; 9686 PetscInt faceVerticesQuadHexSorted[54] = { 9687 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9688 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9689 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9690 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9691 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9692 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9693 }; 9694 PetscInt faceVerticesQuadHex[54] = { 9695 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9696 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9697 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9698 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9699 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9700 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9701 }; 9702 9703 faceSize = faceSizeQuadHex; 9704 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9705 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9706 for (iFace = 0; iFace < 6; ++iFace) { 9707 const PetscInt ii = iFace*faceSizeQuadHex; 9708 PetscInt fVertex, cVertex; 9709 9710 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9711 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9712 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9713 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9714 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9715 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9716 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9717 faceVertices[fVertex] = origVertices[cVertex]; 9718 break; 9719 } 9720 } 9721 } 9722 found = PETSC_TRUE; 9723 break; 9724 } 9725 } 9726 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9727 if (posOriented) {*posOriented = PETSC_TRUE;} 9728 PetscFunctionReturn(0); 9729 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9730 if (!posOrient) { 9731 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9732 for (f = 0; f < faceSize; ++f) { 9733 faceVertices[f] = origVertices[faceSize-1 - f]; 9734 } 9735 } else { 9736 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9737 for (f = 0; f < faceSize; ++f) { 9738 faceVertices[f] = origVertices[f]; 9739 } 9740 } 9741 if (posOriented) {*posOriented = posOrient;} 9742 PetscFunctionReturn(0); 9743 } 9744 9745 #undef __FUNCT__ 9746 #define __FUNCT__ "DMPlexGetOrientedFace" 9747 /* 9748 Given a cell and a face, as a set of vertices, 9749 return the oriented face, as a set of vertices, in faceVertices 9750 The orientation is such that the face normal points out of the cell 9751 */ 9752 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9753 { 9754 const PetscInt *cone = PETSC_NULL; 9755 PetscInt coneSize, v, f, v2; 9756 PetscInt oppositeVertex = -1; 9757 PetscErrorCode ierr; 9758 9759 PetscFunctionBegin; 9760 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9761 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9762 for (v = 0, v2 = 0; v < coneSize; ++v) { 9763 PetscBool found = PETSC_FALSE; 9764 9765 for (f = 0; f < faceSize; ++f) { 9766 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 9767 } 9768 if (found) { 9769 indices[v2] = v; 9770 origVertices[v2] = cone[v]; 9771 ++v2; 9772 } else { 9773 oppositeVertex = v; 9774 } 9775 } 9776 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9777 PetscFunctionReturn(0); 9778 } 9779 9780 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9781 { 9782 switch (i) { 9783 case 0: 9784 switch (j) { 9785 case 0: return 0; 9786 case 1: 9787 switch (k) { 9788 case 0: return 0; 9789 case 1: return 0; 9790 case 2: return 1; 9791 } 9792 case 2: 9793 switch (k) { 9794 case 0: return 0; 9795 case 1: return -1; 9796 case 2: return 0; 9797 } 9798 } 9799 case 1: 9800 switch (j) { 9801 case 0: 9802 switch (k) { 9803 case 0: return 0; 9804 case 1: return 0; 9805 case 2: return -1; 9806 } 9807 case 1: return 0; 9808 case 2: 9809 switch (k) { 9810 case 0: return 1; 9811 case 1: return 0; 9812 case 2: return 0; 9813 } 9814 } 9815 case 2: 9816 switch (j) { 9817 case 0: 9818 switch (k) { 9819 case 0: return 0; 9820 case 1: return 1; 9821 case 2: return 0; 9822 } 9823 case 1: 9824 switch (k) { 9825 case 0: return -1; 9826 case 1: return 0; 9827 case 2: return 0; 9828 } 9829 case 2: return 0; 9830 } 9831 } 9832 return 0; 9833 } 9834 9835 #undef __FUNCT__ 9836 #define __FUNCT__ "DMPlexCreateRigidBody" 9837 /*@C 9838 DMPlexCreateRigidBody - create rigid body modes from coordinates 9839 9840 Collective on DM 9841 9842 Input Arguments: 9843 + dm - the DM 9844 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9845 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9846 9847 Output Argument: 9848 . sp - the null space 9849 9850 Note: This is necessary to take account of Dirichlet conditions on the displacements 9851 9852 Level: advanced 9853 9854 .seealso: MatNullSpaceCreate() 9855 @*/ 9856 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9857 { 9858 MPI_Comm comm = ((PetscObject) dm)->comm; 9859 Vec coordinates, localMode, mode[6]; 9860 PetscSection coordSection; 9861 PetscScalar *coords; 9862 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9863 PetscErrorCode ierr; 9864 9865 PetscFunctionBegin; 9866 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9867 if (dim == 1) { 9868 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9869 PetscFunctionReturn(0); 9870 } 9871 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9872 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9873 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9874 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9875 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9876 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9877 m = (dim*(dim+1))/2; 9878 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9879 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9880 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9881 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9882 /* Assume P1 */ 9883 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9884 for (d = 0; d < dim; ++d) { 9885 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9886 9887 values[d] = 1.0; 9888 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9889 for (v = vStart; v < vEnd; ++v) { 9890 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9891 } 9892 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9893 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9894 } 9895 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9896 for (d = dim; d < dim*(dim+1)/2; ++d) { 9897 PetscInt i, j, k = dim > 2 ? d - dim : d; 9898 9899 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9900 for (v = vStart; v < vEnd; ++v) { 9901 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9902 PetscInt off; 9903 9904 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9905 for (i = 0; i < dim; ++i) { 9906 for (j = 0; j < dim; ++j) { 9907 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9908 } 9909 } 9910 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9911 } 9912 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9913 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9914 } 9915 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9916 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9917 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9918 /* Orthonormalize system */ 9919 for (i = dim; i < m; ++i) { 9920 PetscScalar dots[6]; 9921 9922 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9923 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9924 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9925 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9926 } 9927 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9928 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9929 PetscFunctionReturn(0); 9930 } 9931 9932 #undef __FUNCT__ 9933 #define __FUNCT__ "DMPlexGetHybridBounds" 9934 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9935 { 9936 DM_Plex *mesh = (DM_Plex *) dm->data; 9937 PetscInt dim; 9938 PetscErrorCode ierr; 9939 9940 PetscFunctionBegin; 9941 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9942 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9943 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9944 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9945 if (eMax) *eMax = mesh->hybridPointMax[1]; 9946 if (vMax) *vMax = mesh->hybridPointMax[0]; 9947 PetscFunctionReturn(0); 9948 } 9949 9950 #undef __FUNCT__ 9951 #define __FUNCT__ "DMPlexSetHybridBounds" 9952 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9953 { 9954 DM_Plex *mesh = (DM_Plex *) dm->data; 9955 PetscInt dim; 9956 PetscErrorCode ierr; 9957 9958 PetscFunctionBegin; 9959 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9960 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9961 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9962 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9963 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9964 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9965 PetscFunctionReturn(0); 9966 } 9967 9968 #undef __FUNCT__ 9969 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9970 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9971 { 9972 DM_Plex *mesh = (DM_Plex *) dm->data; 9973 9974 PetscFunctionBegin; 9975 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9976 PetscValidPointer(cellHeight, 2); 9977 *cellHeight = mesh->vtkCellHeight; 9978 PetscFunctionReturn(0); 9979 } 9980 9981 #undef __FUNCT__ 9982 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9983 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9984 { 9985 DM_Plex *mesh = (DM_Plex *) dm->data; 9986 9987 PetscFunctionBegin; 9988 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9989 mesh->vtkCellHeight = cellHeight; 9990 PetscFunctionReturn(0); 9991 } 9992 9993 #undef __FUNCT__ 9994 #define __FUNCT__ "DMPlexInsertFace_Private" 9995 /* 9996 DMPlexInsertFace_Private - Puts a face into the mesh 9997 9998 Not collective 9999 10000 Input Parameters: 10001 + dm - The DMPlex 10002 . numFaceVertex - The number of vertices in the face 10003 . faceVertices - The vertices in the face for dm 10004 . subfaceVertices - The vertices in the face for subdm 10005 . numCorners - The number of vertices in the cell 10006 . cell - A cell in dm containing the face 10007 . subcell - A cell in subdm containing the face 10008 . firstFace - First face in the mesh 10009 - newFacePoint - Next face in the mesh 10010 10011 Output Parameters: 10012 . newFacePoint - Contains next face point number on input, updated on output 10013 10014 Level: developer 10015 */ 10016 PetscErrorCode DMPlexInsertFace_Private(DM dm, DM subdm, PetscInt numFaceVertices, const PetscInt faceVertices[], const PetscInt subfaceVertices[], PetscInt numCorners, PetscInt cell, PetscInt subcell, PetscInt firstFace, PetscInt *newFacePoint) 10017 { 10018 MPI_Comm comm = ((PetscObject) dm)->comm; 10019 DM_Plex *submesh = (DM_Plex *) subdm->data; 10020 const PetscInt *faces; 10021 PetscInt numFaces, coneSize; 10022 PetscErrorCode ierr; 10023 10024 PetscFunctionBegin; 10025 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 10026 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 10027 #if 0 10028 /* Cannot use this because support() has not been constructed yet */ 10029 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 10030 #else 10031 { 10032 PetscInt f; 10033 10034 numFaces = 0; 10035 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 10036 for (f = firstFace; f < *newFacePoint; ++f) { 10037 PetscInt dof, off, d; 10038 10039 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 10040 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 10041 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 10042 for (d = 0; d < dof; ++d) { 10043 const PetscInt p = submesh->cones[off+d]; 10044 PetscInt v; 10045 10046 for (v = 0; v < numFaceVertices; ++v) { 10047 if (subfaceVertices[v] == p) break; 10048 } 10049 if (v == numFaceVertices) break; 10050 } 10051 if (d == dof) { 10052 numFaces = 1; 10053 ((PetscInt *) faces)[0] = f; 10054 } 10055 } 10056 } 10057 #endif 10058 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 10059 else if (numFaces == 1) { 10060 /* Add the other cell neighbor for this face */ 10061 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 10062 } else { 10063 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 10064 PetscBool posOriented; 10065 10066 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10067 origVertices = &orientedVertices[numFaceVertices]; 10068 indices = &orientedVertices[numFaceVertices*2]; 10069 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 10070 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 10071 /* TODO: I know that routine should return a permutation, not the indices */ 10072 for (v = 0; v < numFaceVertices; ++v) { 10073 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 10074 for (ov = 0; ov < numFaceVertices; ++ov) { 10075 if (orientedVertices[ov] == vertex) { 10076 orientedSubVertices[ov] = subvertex; 10077 break; 10078 } 10079 } 10080 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 10081 } 10082 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 10083 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 10084 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10085 ++(*newFacePoint); 10086 } 10087 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 10088 PetscFunctionReturn(0); 10089 } 10090 10091 #undef __FUNCT__ 10092 #define __FUNCT__ "DMPlexCreateSubmesh" 10093 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 10094 { 10095 MPI_Comm comm = ((PetscObject) dm)->comm; 10096 DM_Plex *submesh; 10097 PetscBool boundaryFaces = PETSC_FALSE; 10098 PetscSection coordSection, subCoordSection; 10099 Vec coordinates, subCoordinates; 10100 PetscScalar *coords, *subCoords; 10101 IS labelIS; 10102 const PetscInt *subVertices; 10103 PetscInt *subVerticesActive, *tmpPoints; 10104 PetscInt *subCells = PETSC_NULL; 10105 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 10106 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 10107 PetscInt dim; /* Right now, do not specify dimension */ 10108 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 10109 PetscErrorCode ierr; 10110 10111 PetscFunctionBegin; 10112 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10113 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10114 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10115 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 10116 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10117 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 10118 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 10119 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10120 subface = &face[maxConeSize]; 10121 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 10122 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 10123 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 10124 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 10125 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 10126 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 10127 maxSubCells = numSubVertices; 10128 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 10129 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 10130 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 10131 for (v = 0; v < numSubVertices; ++v) { 10132 const PetscInt vertex = subVertices[v]; 10133 PetscInt *star = PETSC_NULL; 10134 PetscInt starSize, numCells = 0; 10135 10136 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10137 for (p = 0; p < starSize*2; p += 2) { 10138 const PetscInt point = star[p]; 10139 if ((point >= cStart) && (point < cEnd)) { 10140 star[numCells++] = point; 10141 } 10142 } 10143 numOldSubCells = numSubCells; 10144 for (c = 0; c < numCells; ++c) { 10145 const PetscInt cell = star[c]; 10146 PetscInt *closure = PETSC_NULL; 10147 PetscInt closureSize, numCorners = 0, faceSize = 0; 10148 PetscInt cellLoc; 10149 10150 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 10151 if (cellLoc >= 0) continue; 10152 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10153 for (p = 0; p < closureSize*2; p += 2) { 10154 const PetscInt point = closure[p]; 10155 if ((point >= vStart) && (point < vEnd)) { 10156 closure[numCorners++] = point; 10157 } 10158 } 10159 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 10160 for (corner = 0; corner < numCorners; ++corner) { 10161 const PetscInt cellVertex = closure[corner]; 10162 PetscInt subVertex; 10163 10164 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 10165 if (subVertex >= 0) { /* contains submesh vertex */ 10166 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 10167 if (i == faceSize) { 10168 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 10169 face[faceSize] = cellVertex; 10170 subface[faceSize] = subVertex; 10171 ++faceSize; 10172 } 10173 } 10174 } 10175 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10176 if (faceSize >= nFV) { 10177 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10178 if (numSubCells >= maxSubCells) { 10179 PetscInt *tmpCells; 10180 maxSubCells *= 2; 10181 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 10182 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 10183 ierr = PetscFree(subCells);CHKERRQ(ierr); 10184 subCells = tmpCells; 10185 } 10186 /* TOOD: Maybe overestimate then squeeze out empty faces */ 10187 if (faceSize > nFV) { 10188 /* TODO: This is tricky. Maybe just add all faces */ 10189 numSubFaces++; 10190 } else { 10191 numSubFaces++; 10192 } 10193 for (f = 0; f < faceSize; ++f) { 10194 subVerticesActive[subface[f]] = 1; 10195 } 10196 subCells[numSubCells++] = cell; 10197 } 10198 } 10199 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10200 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 10201 } 10202 /* Pick out active subvertices */ 10203 for (v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 10204 if (subVerticesActive[v]) { 10205 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 10206 } 10207 } 10208 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 10209 /* Set cone sizes */ 10210 firstSubVertex = numSubCells; 10211 firstSubFace = numSubCells+numSubVerticesActive; 10212 newFacePoint = firstSubFace; 10213 for (c = 0; c < numSubCells; ++c) { 10214 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 10215 } 10216 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 10217 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 10218 } 10219 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 10220 /* Create face cones */ 10221 for (c = 0; c < numSubCells; ++c) { 10222 const PetscInt cell = subCells[c]; 10223 PetscInt *closure = PETSC_NULL; 10224 PetscInt closureSize, numCorners = 0, faceSize = 0; 10225 10226 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10227 for (p = 0; p < closureSize*2; p += 2) { 10228 const PetscInt point = closure[p]; 10229 if ((point >= vStart) && (point < vEnd)) { 10230 closure[numCorners++] = point; 10231 } 10232 } 10233 for (corner = 0; corner < numCorners; ++corner) { 10234 const PetscInt cellVertex = closure[corner]; 10235 PetscInt subVertex; 10236 10237 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 10238 if (subVertex >= 0) { /* contains submesh vertex */ 10239 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 10240 if (i == faceSize) { 10241 face[faceSize] = cellVertex; 10242 subface[faceSize] = numSubCells+subVertex; 10243 ++faceSize; 10244 } 10245 } 10246 } 10247 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10248 if (faceSize >= nFV) { 10249 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10250 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 10251 /* We have to take all the faces, and discard those in the interior */ 10252 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 10253 #if 0 10254 /* This object just calls insert on each face that comes from subsets() */ 10255 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 10256 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 10257 PointArray faceVec(face->begin(), face->end()); 10258 10259 subsets(faceVec, nFV, inserter); 10260 #endif 10261 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 10262 } 10263 } 10264 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 10265 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 10266 /* Build coordinates */ 10267 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10268 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10269 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 10270 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 10271 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 10272 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 10273 } 10274 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10275 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10276 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 10277 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10278 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10279 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10280 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10281 for (v = 0; v < numSubVerticesActive; ++v) { 10282 const PetscInt vertex = subVerticesActive[v]; 10283 const PetscInt subVertex = firstSubVertex+v; 10284 PetscInt dof, off, sdof, soff; 10285 10286 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10287 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10288 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10289 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10290 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10291 for (d = 0; d < dof; ++d) { 10292 subCoords[soff+d] = coords[off+d]; 10293 } 10294 } 10295 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10296 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10297 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 10298 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10299 10300 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 10301 /* Create map from submesh points to original mesh points */ 10302 submesh = (DM_Plex *) (*subdm)->data; 10303 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 10304 for (c = 0; c < numSubCells; ++c) { 10305 tmpPoints[c] = subCells[c]; 10306 } 10307 for (v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 10308 tmpPoints[v] = subVerticesActive[v-numSubCells]; 10309 } 10310 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 10311 10312 ierr = PetscFree(subCells);CHKERRQ(ierr); 10313 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 10314 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 10315 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 10316 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10317 PetscFunctionReturn(0); 10318 } 10319 10320 #undef __FUNCT__ 10321 #define __FUNCT__ "DMPlexCreateNumbering_Private" 10322 /* We can easily have a form that takes an IS instead */ 10323 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 10324 { 10325 PetscSection section, globalSection; 10326 PetscInt *numbers, p; 10327 PetscErrorCode ierr; 10328 10329 PetscFunctionBegin; 10330 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 10331 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 10332 for (p = pStart; p < pEnd; ++p) { 10333 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 10334 } 10335 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 10336 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 10337 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 10338 for (p = pStart; p < pEnd; ++p) { 10339 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 10340 } 10341 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 10342 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 10343 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 10344 PetscFunctionReturn(0); 10345 } 10346 10347 #undef __FUNCT__ 10348 #define __FUNCT__ "DMPlexGetCellNumbering" 10349 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 10350 { 10351 DM_Plex *mesh = (DM_Plex *) dm->data; 10352 PetscInt cellHeight, cStart, cEnd, cMax; 10353 PetscErrorCode ierr; 10354 10355 PetscFunctionBegin; 10356 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10357 if (!mesh->globalCellNumbers) { 10358 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10359 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 10360 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10361 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 10362 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 10363 } 10364 *globalCellNumbers = mesh->globalCellNumbers; 10365 PetscFunctionReturn(0); 10366 } 10367 10368 #undef __FUNCT__ 10369 #define __FUNCT__ "DMPlexGetVertexNumbering" 10370 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 10371 { 10372 DM_Plex *mesh = (DM_Plex *) dm->data; 10373 PetscInt vStart, vEnd, vMax; 10374 PetscErrorCode ierr; 10375 10376 PetscFunctionBegin; 10377 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10378 if (!mesh->globalVertexNumbers) { 10379 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10380 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10381 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 10382 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 10383 } 10384 *globalVertexNumbers = mesh->globalVertexNumbers; 10385 PetscFunctionReturn(0); 10386 } 10387 10388 #undef __FUNCT__ 10389 #define __FUNCT__ "DMPlexGetSubpointMap" 10390 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 10391 { 10392 DM_Plex *mesh = (DM_Plex *) dm->data; 10393 10394 PetscFunctionBegin; 10395 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10396 PetscValidPointer(subpointMap, 2); 10397 *subpointMap = mesh->subpointMap; 10398 PetscFunctionReturn(0); 10399 } 10400 10401 #undef __FUNCT__ 10402 #define __FUNCT__ "DMPlexSetSubpointMap" 10403 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 10404 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 10405 { 10406 DM_Plex *mesh = (DM_Plex *) dm->data; 10407 10408 PetscFunctionBegin; 10409 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10410 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 10411 mesh->subpointMap = subpointMap; 10412 PetscFunctionReturn(0); 10413 } 10414 10415 #undef __FUNCT__ 10416 #define __FUNCT__ "DMPlexGetScale" 10417 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10418 { 10419 DM_Plex *mesh = (DM_Plex *) dm->data; 10420 10421 PetscFunctionBegin; 10422 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10423 PetscValidPointer(scale, 3); 10424 *scale = mesh->scale[unit]; 10425 PetscFunctionReturn(0); 10426 } 10427 10428 #undef __FUNCT__ 10429 #define __FUNCT__ "DMPlexSetScale" 10430 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 10431 { 10432 DM_Plex *mesh = (DM_Plex *) dm->data; 10433 10434 PetscFunctionBegin; 10435 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10436 mesh->scale[unit] = scale; 10437 PetscFunctionReturn(0); 10438 } 10439 10440 10441 /******************************************************************************* 10442 This should be in a separate Discretization object, but I am not sure how to lay 10443 it out yet, so I am stuffing things here while I experiment. 10444 *******************************************************************************/ 10445 #undef __FUNCT__ 10446 #define __FUNCT__ "DMPlexSetFEMIntegration" 10447 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 10448 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10449 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10450 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10451 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10452 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 10453 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10454 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10455 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10456 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10457 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10458 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10459 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10460 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10461 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10462 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10463 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 10464 { 10465 DM_Plex *mesh = (DM_Plex *) dm->data; 10466 10467 PetscFunctionBegin; 10468 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10469 mesh->integrateResidualFEM = integrateResidualFEM; 10470 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 10471 mesh->integrateJacobianFEM = integrateJacobianFEM; 10472 PetscFunctionReturn(0); 10473 } 10474 10475 #undef __FUNCT__ 10476 #define __FUNCT__ "DMPlexProjectFunctionLocal" 10477 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 10478 { 10479 Vec coordinates; 10480 PetscSection section, cSection; 10481 PetscInt dim, vStart, vEnd, v, c, d; 10482 PetscScalar *values, *cArray; 10483 PetscReal *coords; 10484 PetscErrorCode ierr; 10485 10486 PetscFunctionBegin; 10487 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10488 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10489 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 10490 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10491 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10492 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 10493 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 10494 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 10495 for (v = vStart; v < vEnd; ++v) { 10496 PetscInt dof, off; 10497 10498 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 10499 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 10500 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 10501 for (d = 0; d < dof; ++d) { 10502 coords[d] = PetscRealPart(cArray[off+d]); 10503 } 10504 for (c = 0; c < numComp; ++c) { 10505 values[c] = (*funcs[c])(coords); 10506 } 10507 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 10508 } 10509 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 10510 /* Temporary, must be replaced by a projection on the finite element basis */ 10511 { 10512 PetscInt eStart = 0, eEnd = 0, e, depth; 10513 10514 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 10515 --depth; 10516 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 10517 for (e = eStart; e < eEnd; ++e) { 10518 const PetscInt *cone = PETSC_NULL; 10519 PetscInt coneSize, d; 10520 PetscScalar *coordsA, *coordsB; 10521 10522 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 10523 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 10524 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 10525 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 10526 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 10527 for (d = 0; d < dim; ++d) { 10528 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 10529 } 10530 for (c = 0; c < numComp; ++c) { 10531 values[c] = (*funcs[c])(coords); 10532 } 10533 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 10534 } 10535 } 10536 10537 ierr = PetscFree(coords);CHKERRQ(ierr); 10538 ierr = PetscFree(values);CHKERRQ(ierr); 10539 #if 0 10540 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 10541 PetscReal detJ; 10542 10543 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10544 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 10545 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 10546 10547 for (PetscInt c = cStart; c < cEnd; ++c) { 10548 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 10549 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 10550 const int oSize = pV.getSize(); 10551 int v = 0; 10552 10553 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 10554 for (PetscInt cl = 0; cl < oSize; ++cl) { 10555 const PetscInt fDim; 10556 10557 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10558 if (pointDim) { 10559 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10560 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10561 } 10562 } 10563 } 10564 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10565 pV.clear(); 10566 } 10567 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10568 ierr = PetscFree(values);CHKERRQ(ierr); 10569 #endif 10570 PetscFunctionReturn(0); 10571 } 10572 10573 #undef __FUNCT__ 10574 #define __FUNCT__ "DMPlexProjectFunction" 10575 /*@C 10576 DMPlexProjectFunction - This projects the given function into the function space provided. 10577 10578 Input Parameters: 10579 + dm - The DM 10580 . numComp - The number of components (functions) 10581 . funcs - The coordinate functions to evaluate 10582 - mode - The insertion mode for values 10583 10584 Output Parameter: 10585 . X - vector 10586 10587 Level: developer 10588 10589 Note: 10590 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10591 We will eventually fix it. 10592 10593 ,seealso: DMPlexComputeL2Diff() 10594 */ 10595 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10596 { 10597 Vec localX; 10598 PetscErrorCode ierr; 10599 10600 PetscFunctionBegin; 10601 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10602 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10603 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10604 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10605 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10606 PetscFunctionReturn(0); 10607 } 10608 10609 #undef __FUNCT__ 10610 #define __FUNCT__ "DMPlexComputeL2Diff" 10611 /*@C 10612 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10613 10614 Input Parameters: 10615 + dm - The DM 10616 . quad - The PetscQuadrature object for each field 10617 . funcs - The functions to evaluate for each field component 10618 - X - The coefficient vector u_h 10619 10620 Output Parameter: 10621 . diff - The diff ||u - u_h||_2 10622 10623 Level: developer 10624 10625 .seealso: DMPlexProjectFunction() 10626 */ 10627 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10628 { 10629 const PetscInt debug = 0; 10630 PetscSection section; 10631 Vec localX; 10632 PetscReal *coords, *v0, *J, *invJ, detJ; 10633 PetscReal localDiff = 0.0; 10634 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10635 PetscErrorCode ierr; 10636 10637 PetscFunctionBegin; 10638 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10639 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10640 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10641 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10642 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10643 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10644 for (field = 0; field < numFields; ++field) { 10645 numComponents += quad[field].numComponents; 10646 } 10647 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10648 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10649 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10650 for (c = cStart; c < cEnd; ++c) { 10651 const PetscScalar *x; 10652 PetscReal elemDiff = 0.0; 10653 10654 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10655 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10656 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10657 10658 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10659 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10660 const PetscReal *quadPoints = quad[field].quadPoints; 10661 const PetscReal *quadWeights = quad[field].quadWeights; 10662 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10663 const PetscInt numBasisComps = quad[field].numComponents; 10664 const PetscReal *basis = quad[field].basis; 10665 PetscInt q, d, e, fc, f; 10666 10667 if (debug) { 10668 char title[1024]; 10669 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10670 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10671 } 10672 for (q = 0; q < numQuadPoints; ++q) { 10673 for (d = 0; d < dim; d++) { 10674 coords[d] = v0[d]; 10675 for (e = 0; e < dim; e++) { 10676 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10677 } 10678 } 10679 for (fc = 0; fc < numBasisComps; ++fc) { 10680 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10681 PetscReal interpolant = 0.0; 10682 for (f = 0; f < numBasisFuncs; ++f) { 10683 const PetscInt fidx = f*numBasisComps+fc; 10684 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10685 } 10686 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10687 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10688 } 10689 } 10690 comp += numBasisComps; 10691 fieldOffset += numBasisFuncs*numBasisComps; 10692 } 10693 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10694 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10695 localDiff += elemDiff; 10696 } 10697 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10698 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10699 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10700 *diff = PetscSqrtReal(*diff); 10701 PetscFunctionReturn(0); 10702 } 10703 10704 #undef __FUNCT__ 10705 #define __FUNCT__ "DMPlexComputeResidualFEM" 10706 /*@ 10707 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10708 10709 Input Parameters: 10710 + dm - The mesh 10711 . X - Local input vector 10712 - user - The user context 10713 10714 Output Parameter: 10715 . F - Local output vector 10716 10717 Note: 10718 The second member of the user context must be an FEMContext. 10719 10720 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10721 like a GPU, or vectorize on a multicore machine. 10722 10723 .seealso: DMPlexComputeJacobianActionFEM() 10724 */ 10725 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10726 { 10727 DM_Plex *mesh = (DM_Plex *) dm->data; 10728 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10729 PetscQuadrature *quad = fem->quad; 10730 PetscSection section; 10731 PetscReal *v0, *J, *invJ, *detJ; 10732 PetscScalar *elemVec, *u; 10733 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10734 PetscInt cellDof = 0, numComponents = 0; 10735 PetscErrorCode ierr; 10736 10737 PetscFunctionBegin; 10738 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10739 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10740 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10741 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10742 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10743 numCells = cEnd - cStart; 10744 for (field = 0; field < numFields; ++field) { 10745 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10746 numComponents += quad[field].numComponents; 10747 } 10748 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10749 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10750 ierr = PetscMalloc6(numCells*cellDof,PetscScalar,&u,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof,PetscScalar,&elemVec);CHKERRQ(ierr); 10751 for (c = cStart; c < cEnd; ++c) { 10752 const PetscScalar *x; 10753 PetscInt i; 10754 10755 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10756 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10757 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10758 10759 for (i = 0; i < cellDof; ++i) { 10760 u[c*cellDof+i] = x[i]; 10761 } 10762 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10763 } 10764 for (field = 0; field < numFields; ++field) { 10765 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10766 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10767 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10768 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10769 /* Conforming batches */ 10770 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10771 PetscInt numBlocks = 1; 10772 PetscInt batchSize = numBlocks * blockSize; 10773 PetscInt numBatches = numBatchesTmp; 10774 PetscInt numChunks = numCells / (numBatches*batchSize); 10775 /* Remainder */ 10776 PetscInt numRemainder = numCells % (numBatches * batchSize); 10777 PetscInt offset = numCells - numRemainder; 10778 10779 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10780 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10781 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10782 } 10783 for (c = cStart; c < cEnd; ++c) { 10784 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10785 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10786 } 10787 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10788 if (mesh->printFEM) { 10789 PetscMPIInt rank, numProcs; 10790 PetscInt p; 10791 10792 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10793 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10794 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10795 for (p = 0; p < numProcs; ++p) { 10796 if (p == rank) { 10797 Vec f; 10798 10799 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10800 ierr = VecCopy(F, f);CHKERRQ(ierr); 10801 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10802 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10803 ierr = VecDestroy(&f);CHKERRQ(ierr); 10804 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10805 } 10806 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10807 } 10808 } 10809 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10810 PetscFunctionReturn(0); 10811 } 10812 10813 #undef __FUNCT__ 10814 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10815 /*@C 10816 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10817 10818 Input Parameters: 10819 + dm - The mesh 10820 . J - The Jacobian shell matrix 10821 . X - Local input vector 10822 - user - The user context 10823 10824 Output Parameter: 10825 . F - Local output vector 10826 10827 Note: 10828 The second member of the user context must be an FEMContext. 10829 10830 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10831 like a GPU, or vectorize on a multicore machine. 10832 10833 .seealso: DMPlexComputeResidualFEM() 10834 */ 10835 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10836 { 10837 DM_Plex *mesh = (DM_Plex *) dm->data; 10838 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10839 PetscQuadrature *quad = fem->quad; 10840 PetscSection section; 10841 JacActionCtx *jctx; 10842 PetscReal *v0, *J, *invJ, *detJ; 10843 PetscScalar *elemVec, *u, *a; 10844 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10845 PetscInt cellDof = 0; 10846 PetscErrorCode ierr; 10847 10848 PetscFunctionBegin; 10849 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10850 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10851 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10852 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10853 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10854 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10855 numCells = cEnd - cStart; 10856 for (field = 0; field < numFields; ++field) { 10857 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10858 } 10859 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10860 ierr = PetscMalloc7(numCells*cellDof,PetscScalar,&u,numCells*cellDof,PetscScalar,&a,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof,PetscScalar,&elemVec);CHKERRQ(ierr); 10861 for (c = cStart; c < cEnd; ++c) { 10862 const PetscScalar *x; 10863 PetscInt i; 10864 10865 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10866 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10867 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10868 for (i = 0; i < cellDof; ++i) { 10869 u[c*cellDof+i] = x[i]; 10870 } 10871 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10872 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10873 for (i = 0; i < cellDof; ++i) { 10874 a[c*cellDof+i] = x[i]; 10875 } 10876 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10877 } 10878 for (field = 0; field < numFields; ++field) { 10879 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10880 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10881 /* Conforming batches */ 10882 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10883 PetscInt numBlocks = 1; 10884 PetscInt batchSize = numBlocks * blockSize; 10885 PetscInt numBatches = numBatchesTmp; 10886 PetscInt numChunks = numCells / (numBatches*batchSize); 10887 /* Remainder */ 10888 PetscInt numRemainder = numCells % (numBatches * batchSize); 10889 PetscInt offset = numCells - numRemainder; 10890 10891 ierr = (*mesh->integrateJacobianActionFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, a, v0, J, invJ, detJ, fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, elemVec);CHKERRQ(ierr); 10892 ierr = (*mesh->integrateJacobianActionFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &a[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10893 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10894 } 10895 for (c = cStart; c < cEnd; ++c) { 10896 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10897 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10898 } 10899 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10900 if (mesh->printFEM) { 10901 PetscMPIInt rank, numProcs; 10902 PetscInt p; 10903 10904 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10905 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10906 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10907 for (p = 0; p < numProcs; ++p) { 10908 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10909 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10910 } 10911 } 10912 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10913 PetscFunctionReturn(0); 10914 } 10915 10916 #undef __FUNCT__ 10917 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10918 /*@ 10919 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10920 10921 Input Parameters: 10922 + dm - The mesh 10923 . X - Local input vector 10924 - user - The user context 10925 10926 Output Parameter: 10927 . Jac - Jacobian matrix 10928 10929 Note: 10930 The second member of the user context must be an FEMContext. 10931 10932 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10933 like a GPU, or vectorize on a multicore machine. 10934 10935 .seealso: FormFunctionLocal() 10936 */ 10937 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10938 { 10939 DM_Plex *mesh = (DM_Plex *) dm->data; 10940 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10941 PetscQuadrature *quad = fem->quad; 10942 PetscSection section; 10943 PetscReal *v0, *J, *invJ, *detJ; 10944 PetscScalar *elemMat, *u; 10945 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10946 PetscInt cellDof = 0, numComponents = 0; 10947 PetscBool isShell; 10948 PetscErrorCode ierr; 10949 10950 PetscFunctionBegin; 10951 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10952 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10953 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10954 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10955 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10956 numCells = cEnd - cStart; 10957 for (field = 0; field < numFields; ++field) { 10958 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10959 numComponents += quad[field].numComponents; 10960 } 10961 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10962 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10963 ierr = PetscMalloc6(numCells*cellDof,PetscScalar,&u,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof*cellDof,PetscScalar,&elemMat);CHKERRQ(ierr); 10964 for (c = cStart; c < cEnd; ++c) { 10965 const PetscScalar *x; 10966 PetscInt i; 10967 10968 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10969 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10970 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10971 10972 for (i = 0; i < cellDof; ++i) { 10973 u[c*cellDof+i] = x[i]; 10974 } 10975 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10976 } 10977 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10978 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10979 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10980 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10981 PetscInt fieldJ; 10982 10983 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10984 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10985 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10986 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10987 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10988 /* Conforming batches */ 10989 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10990 PetscInt numBlocks = 1; 10991 PetscInt batchSize = numBlocks * blockSize; 10992 PetscInt numBatches = numBatchesTmp; 10993 PetscInt numChunks = numCells / (numBatches*batchSize); 10994 /* Remainder */ 10995 PetscInt numRemainder = numCells % (numBatches * batchSize); 10996 PetscInt offset = numCells - numRemainder; 10997 10998 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10999 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 11000 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 11001 } 11002 } 11003 for (c = cStart; c < cEnd; ++c) { 11004 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 11005 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 11006 } 11007 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 11008 11009 /* Assemble matrix, using the 2-step process: 11010 MatAssemblyBegin(), MatAssemblyEnd(). */ 11011 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11012 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11013 11014 if (mesh->printFEM) { 11015 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 11016 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 11017 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 11018 } 11019 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 11020 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 11021 if (isShell) { 11022 JacActionCtx *jctx; 11023 11024 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 11025 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 11026 } 11027 *str = SAME_NONZERO_PATTERN; 11028 PetscFunctionReturn(0); 11029 } 11030 11031 11032 #undef __FUNCT__ 11033 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 11034 /*@C 11035 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 11036 the local section and an SF describing the section point overlap. 11037 11038 Input Parameters: 11039 + s - The PetscSection for the local field layout 11040 . sf - The SF describing parallel layout of the section points 11041 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 11042 . label - The label specifying the points 11043 - labelValue - The label stratum specifying the points 11044 11045 Output Parameter: 11046 . gsection - The PetscSection for the global field layout 11047 11048 Note: This gives negative sizes and offsets to points not owned by this process 11049 11050 Level: developer 11051 11052 .seealso: PetscSectionCreate() 11053 @*/ 11054 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 11055 { 11056 PetscInt *neg; 11057 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 11058 PetscErrorCode ierr; 11059 11060 PetscFunctionBegin; 11061 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 11062 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 11063 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 11064 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 11065 /* Mark ghost points with negative dof */ 11066 for (p = pStart; p < pEnd; ++p) { 11067 PetscInt value; 11068 11069 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 11070 if (value != labelValue) continue; 11071 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 11072 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 11073 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 11074 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 11075 neg[p-pStart] = -(dof+1); 11076 } 11077 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 11078 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 11079 if (nroots >= 0) { 11080 if (nroots > pEnd - pStart) { 11081 PetscInt *tmpDof; 11082 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11083 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 11084 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11085 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11086 for (p = pStart; p < pEnd; ++p) { 11087 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 11088 } 11089 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 11090 } else { 11091 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11092 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11093 } 11094 } 11095 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 11096 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11097 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 11098 (*gsection)->atlasOff[p] = off; 11099 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 11100 } 11101 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 11102 globalOff -= off; 11103 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11104 (*gsection)->atlasOff[p] += globalOff; 11105 neg[p] = -((*gsection)->atlasOff[p]+1); 11106 } 11107 /* Put in negative offsets for ghost points */ 11108 if (nroots >= 0) { 11109 if (nroots > pEnd - pStart) { 11110 PetscInt *tmpOff; 11111 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11112 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 11113 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11114 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11115 for (p = pStart; p < pEnd; ++p) { 11116 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 11117 } 11118 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 11119 } else { 11120 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11121 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11122 } 11123 } 11124 ierr = PetscFree(neg);CHKERRQ(ierr); 11125 PetscFunctionReturn(0); 11126 } 11127