1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex *) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 if (markers) { 167 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 168 } 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for(p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for(v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for(e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for(c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = PETSC_NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm = ((PetscObject) dm)->comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 284 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 285 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 286 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 287 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 288 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 289 if (depth == 1) { 290 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 291 pEnd = pEnd - pStart; 292 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 293 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 294 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 295 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 296 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 297 pEnd = pEnd - pStart; 298 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 299 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 300 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 301 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 302 } else { 303 for (d = 0; d <= dim; d++) { 304 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 305 pEnd = pEnd - pStart; 306 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 307 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 308 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 309 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 310 } 311 } 312 ierr = PetscFree(sizes);CHKERRQ(ierr); 313 } 314 PetscFunctionReturn(0); 315 } 316 317 #undef __FUNCT__ 318 #define __FUNCT__ "DMView_Plex" 319 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 320 { 321 PetscBool iascii, isbinary; 322 PetscErrorCode ierr; 323 324 PetscFunctionBegin; 325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 326 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 327 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 329 if (iascii) { 330 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 331 #if 0 332 } else if (isbinary) { 333 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 334 #endif 335 } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name); 336 PetscFunctionReturn(0); 337 } 338 339 #undef __FUNCT__ 340 #define __FUNCT__ "DMDestroy_Plex" 341 PetscErrorCode DMDestroy_Plex(DM dm) 342 { 343 DM_Plex *mesh = (DM_Plex *) dm->data; 344 DMLabel next = mesh->labels; 345 PetscErrorCode ierr; 346 347 PetscFunctionBegin; 348 if (--mesh->refct > 0) {PetscFunctionReturn(0);} 349 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 350 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 352 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 353 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 355 while(next) { 356 DMLabel tmp = next->next; 357 358 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 359 next = tmp; 360 } 361 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 362 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 364 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 365 ierr = PetscFree(mesh);CHKERRQ(ierr); 366 PetscFunctionReturn(0); 367 } 368 369 #undef __FUNCT__ 370 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 371 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 372 { 373 const PetscInt *support = PETSC_NULL; 374 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 375 PetscErrorCode ierr; 376 377 PetscFunctionBegin; 378 if (useClosure) { 379 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 380 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 381 for (s = 0; s < supportSize; ++s) { 382 const PetscInt *cone = PETSC_NULL; 383 PetscInt coneSize, c, q; 384 385 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 386 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 387 for (c = 0; c < coneSize; ++c) { 388 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 389 if (cone[c] == adj[q]) break; 390 } 391 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 392 } 393 } 394 } else { 395 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 396 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 397 for (s = 0; s < supportSize; ++s) { 398 const PetscInt *cone = PETSC_NULL; 399 PetscInt coneSize, c, q; 400 401 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 402 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 403 for (c = 0; c < coneSize; ++c) { 404 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 405 if (cone[c] == adj[q]) break; 406 } 407 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 408 } 409 } 410 } 411 *adjSize = numAdj; 412 PetscFunctionReturn(0); 413 } 414 415 #undef __FUNCT__ 416 #define __FUNCT__ "DMPlexGetAdjacency_Private" 417 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 418 { 419 const PetscInt *star = tmpClosure; 420 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 421 PetscErrorCode ierr; 422 423 PetscFunctionBegin; 424 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr); 425 for (s = 2; s < starSize*2; s += 2) { 426 const PetscInt *closure = PETSC_NULL; 427 PetscInt closureSize, c, q; 428 429 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 430 for (c = 0; c < closureSize*2; c += 2) { 431 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 432 if (closure[c] == adj[q]) break; 433 } 434 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 435 } 436 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 437 } 438 *adjSize = numAdj; 439 PetscFunctionReturn(0); 440 } 441 442 #undef __FUNCT__ 443 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 444 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 445 { 446 DM_Plex *mesh = (DM_Plex *) dm->data; 447 448 PetscFunctionBegin; 449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 450 mesh->preallocCenterDim = preallocCenterDim; 451 PetscFunctionReturn(0); 452 } 453 454 #undef __FUNCT__ 455 #define __FUNCT__ "DMPlexPreallocateOperator" 456 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 457 { 458 DM_Plex *mesh = (DM_Plex *) dm->data; 459 MPI_Comm comm = ((PetscObject) dm)->comm; 460 PetscSF sf, sfDof, sfAdj; 461 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 462 PetscInt nleaves, l, p; 463 const PetscInt *leaves; 464 const PetscSFNode *remotes; 465 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 466 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 467 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 468 PetscLayout rLayout; 469 PetscInt locRows, rStart, rEnd, r; 470 PetscMPIInt size; 471 PetscBool useClosure, debug = PETSC_FALSE; 472 PetscErrorCode ierr; 473 474 PetscFunctionBegin; 475 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 476 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 477 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 478 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 479 /* Create dof SF based on point SF */ 480 if (debug) { 481 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 487 } 488 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 489 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 490 if (debug) { 491 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 492 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 493 } 494 /* Create section for dof adjacency (dof ==> # adj dof) */ 495 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 496 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 497 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 498 if (mesh->preallocCenterDim == dim) { 499 useClosure = PETSC_FALSE; 500 } else if (mesh->preallocCenterDim == 0) { 501 useClosure = PETSC_TRUE; 502 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 503 504 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 505 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 510 /* Fill in the ghost dofs on the interface */ 511 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 512 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 513 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 514 maxClosureSize = (PetscInt) (2*PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1)); 515 maxAdjSize = (PetscInt) (pow((PetscReal) mesh->maxConeSize, depth)*pow((PetscReal) 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(pow(mesh->maxConeSize, depth)+1, pow(mesh->maxSupportSize, depth)+1); 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 #ifndef 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 = (PetscInt) (2*PetscMax(PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1), depth+1)); 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 = (PetscInt) (pow((PetscReal) mesh->maxSupportSize, depth)+1); 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 = (PetscInt) (pow((PetscReal) mesh->maxConeSize, height)+1); 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 MPI_Comm comm = ((PetscObject) dm)->comm; 2485 PetscInt cellDim; 2486 PetscErrorCode ierr; 2487 2488 PetscFunctionBegin; 2489 PetscValidPointer(numFaceVertices,3); 2490 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2491 switch(cellDim) { 2492 case 0: 2493 *numFaceVertices = 0; 2494 break; 2495 case 1: 2496 *numFaceVertices = 1; 2497 break; 2498 case 2: 2499 switch(numCorners) { 2500 case 3: /* triangle */ 2501 *numFaceVertices = 2; /* Edge has 2 vertices */ 2502 break; 2503 case 4: /* quadrilateral */ 2504 *numFaceVertices = 2; /* Edge has 2 vertices */ 2505 break; 2506 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2507 *numFaceVertices = 3; /* Edge has 3 vertices */ 2508 break; 2509 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2510 *numFaceVertices = 3; /* Edge has 3 vertices */ 2511 break; 2512 default: 2513 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2514 } 2515 break; 2516 case 3: 2517 switch(numCorners) { 2518 case 4: /* tetradehdron */ 2519 *numFaceVertices = 3; /* Face has 3 vertices */ 2520 break; 2521 case 6: /* tet cohesive cells */ 2522 *numFaceVertices = 4; /* Face has 4 vertices */ 2523 break; 2524 case 8: /* hexahedron */ 2525 *numFaceVertices = 4; /* Face has 4 vertices */ 2526 break; 2527 case 9: /* tet cohesive Lagrange cells */ 2528 *numFaceVertices = 6; /* Face has 6 vertices */ 2529 break; 2530 case 10: /* quadratic tetrahedron */ 2531 *numFaceVertices = 6; /* Face has 6 vertices */ 2532 break; 2533 case 12: /* hex cohesive Lagrange cells */ 2534 *numFaceVertices = 6; /* Face has 6 vertices */ 2535 break; 2536 case 18: /* quadratic tet cohesive Lagrange cells */ 2537 *numFaceVertices = 6; /* Face has 6 vertices */ 2538 break; 2539 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2540 *numFaceVertices = 9; /* Face has 9 vertices */ 2541 break; 2542 default: 2543 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2544 } 2545 break; 2546 default: 2547 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2548 } 2549 PetscFunctionReturn(0); 2550 } 2551 2552 #undef __FUNCT__ 2553 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2554 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2555 { 2556 const PetscInt maxFaceCases = 30; 2557 PetscInt numFaceCases = 0; 2558 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2559 PetscInt *off, *adj; 2560 PetscInt *neighborCells, *tmpClosure; 2561 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2562 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2563 PetscErrorCode ierr; 2564 2565 PetscFunctionBegin; 2566 /* For parallel partitioning, I think you have to communicate supports */ 2567 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2568 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2569 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2570 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2571 if (cEnd - cStart == 0) { 2572 if (numVertices) *numVertices = 0; 2573 if (offsets) *offsets = PETSC_NULL; 2574 if (adjacency) *adjacency = PETSC_NULL; 2575 PetscFunctionReturn(0); 2576 } 2577 numCells = cEnd - cStart; 2578 /* Setup face recognition */ 2579 { 2580 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 */ 2581 2582 for (c = cStart; c < cEnd; ++c) { 2583 PetscInt corners; 2584 2585 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2586 if (!cornersSeen[corners]) { 2587 PetscInt nFV; 2588 2589 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2590 cornersSeen[corners] = 1; 2591 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2592 numFaceVertices[numFaceCases++] = nFV; 2593 } 2594 } 2595 } 2596 maxClosure = (PetscInt) (2*PetscMax(pow((PetscReal) maxConeSize, depth)+1, pow((PetscReal) maxSupportSize, depth)+1)); 2597 maxNeighbors = (PetscInt) (pow((PetscReal) maxConeSize, depth)*pow((PetscReal) maxSupportSize, depth)+1); 2598 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2599 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2600 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2601 /* Count neighboring cells */ 2602 for (cell = cStart; cell < cEnd; ++cell) { 2603 PetscInt numNeighbors = maxNeighbors, n; 2604 2605 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2606 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2607 for (n = 0; n < numNeighbors; ++n) { 2608 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2609 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2610 PetscInt meetSize = 0; 2611 const PetscInt *meet = PETSC_NULL; 2612 2613 if (cellPair[0] == cellPair[1]) continue; 2614 if (!found) { 2615 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2616 if (meetSize) { 2617 PetscInt f; 2618 2619 for (f = 0; f < numFaceCases; ++f) { 2620 if (numFaceVertices[f] == meetSize) { 2621 found = PETSC_TRUE; 2622 break; 2623 } 2624 } 2625 } 2626 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2627 } 2628 if (found) { 2629 ++off[cell-cStart+1]; 2630 } 2631 } 2632 } 2633 /* Prefix sum */ 2634 for (cell = 1; cell <= numCells; ++cell) { 2635 off[cell] += off[cell-1]; 2636 } 2637 if (adjacency) { 2638 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2639 /* Get neighboring cells */ 2640 for (cell = cStart; cell < cEnd; ++cell) { 2641 PetscInt numNeighbors = maxNeighbors, n; 2642 PetscInt cellOffset = 0; 2643 2644 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2645 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2646 for (n = 0; n < numNeighbors; ++n) { 2647 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2648 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2649 PetscInt meetSize = 0; 2650 const PetscInt *meet = PETSC_NULL; 2651 2652 if (cellPair[0] == cellPair[1]) continue; 2653 if (!found) { 2654 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2655 if (meetSize) { 2656 PetscInt f; 2657 2658 for (f = 0; f < numFaceCases; ++f) { 2659 if (numFaceVertices[f] == meetSize) { 2660 found = PETSC_TRUE; 2661 break; 2662 } 2663 } 2664 } 2665 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2666 } 2667 if (found) { 2668 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2669 ++cellOffset; 2670 } 2671 } 2672 } 2673 } 2674 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2675 if (numVertices) *numVertices = numCells; 2676 if (offsets) *offsets = off; 2677 if (adjacency) *adjacency = adj; 2678 PetscFunctionReturn(0); 2679 } 2680 2681 #ifdef PETSC_HAVE_CHACO 2682 #ifdef PETSC_HAVE_UNISTD_H 2683 #include <unistd.h> 2684 #endif 2685 /* Chaco does not have an include file */ 2686 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2687 float *ewgts, float *x, float *y, float *z, char *outassignname, 2688 char *outfilename, short *assignment, int architecture, int ndims_tot, 2689 int mesh_dims[3], double *goal, int global_method, int local_method, 2690 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2691 2692 extern int FREE_GRAPH; 2693 2694 #undef __FUNCT__ 2695 #define __FUNCT__ "DMPlexPartition_Chaco" 2696 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2697 { 2698 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2699 MPI_Comm comm = ((PetscObject) dm)->comm; 2700 int nvtxs = numVertices; /* number of vertices in full graph */ 2701 int *vwgts = NULL; /* weights for all vertices */ 2702 float *ewgts = NULL; /* weights for all edges */ 2703 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2704 char *outassignname = NULL; /* name of assignment output file */ 2705 char *outfilename = NULL; /* output file name */ 2706 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2707 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2708 int mesh_dims[3]; /* dimensions of mesh of processors */ 2709 double *goal = NULL; /* desired set sizes for each set */ 2710 int global_method = 1; /* global partitioning algorithm */ 2711 int local_method = 1; /* local partitioning algorithm */ 2712 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2713 int vmax = 200; /* how many vertices to coarsen down to? */ 2714 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2715 double eigtol = 0.001; /* tolerance on eigenvectors */ 2716 long seed = 123636512; /* for random graph mutations */ 2717 short int *assignment; /* Output partition */ 2718 int fd_stdout, fd_pipe[2]; 2719 PetscInt *points; 2720 PetscMPIInt commSize; 2721 int i, v, p; 2722 PetscErrorCode ierr; 2723 2724 PetscFunctionBegin; 2725 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2726 if (!numVertices) { 2727 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2728 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2729 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2730 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2731 PetscFunctionReturn(0); 2732 } 2733 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2734 for (i = 0; i < start[numVertices]; ++i) { 2735 ++adjacency[i]; 2736 } 2737 if (global_method == INERTIAL_METHOD) { 2738 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2739 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2740 } 2741 mesh_dims[0] = commSize; 2742 mesh_dims[1] = 1; 2743 mesh_dims[2] = 1; 2744 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2745 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2746 /* TODO: check error codes for UNIX calls */ 2747 #ifdef PETSC_HAVE_UNISTD_H 2748 { 2749 int piperet; 2750 piperet = pipe(fd_pipe); 2751 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2752 fd_stdout = dup(1); 2753 close(1); 2754 dup2(fd_pipe[1], 1); 2755 } 2756 #endif 2757 ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2758 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2759 vmax, ndims, eigtol, seed); 2760 #ifdef PETSC_HAVE_UNISTD_H 2761 { 2762 char msgLog[10000]; 2763 int count; 2764 2765 fflush(stdout); 2766 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2767 if (count < 0) count = 0; 2768 msgLog[count] = 0; 2769 close(1); 2770 dup2(fd_stdout, 1); 2771 close(fd_stdout); 2772 close(fd_pipe[0]); 2773 close(fd_pipe[1]); 2774 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2775 } 2776 #endif 2777 /* Convert to PetscSection+IS */ 2778 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2779 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2780 for (v = 0; v < nvtxs; ++v) { 2781 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2782 } 2783 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2784 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2785 for (p = 0, i = 0; p < commSize; ++p) { 2786 for (v = 0; v < nvtxs; ++v) { 2787 if (assignment[v] == p) points[i++] = v; 2788 } 2789 } 2790 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2791 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2792 if (global_method == INERTIAL_METHOD) { 2793 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2794 } 2795 ierr = PetscFree(assignment);CHKERRQ(ierr); 2796 for (i = 0; i < start[numVertices]; ++i) { 2797 --adjacency[i]; 2798 } 2799 PetscFunctionReturn(0); 2800 } 2801 #endif 2802 2803 #ifdef PETSC_HAVE_PARMETIS 2804 #undef __FUNCT__ 2805 #define __FUNCT__ "DMPlexPartition_ParMetis" 2806 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2807 { 2808 PetscFunctionBegin; 2809 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2810 PetscFunctionReturn(0); 2811 } 2812 #endif 2813 2814 #undef __FUNCT__ 2815 #define __FUNCT__ "DMPlexEnlargePartition" 2816 /* Expand the partition by BFS on the adjacency graph */ 2817 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) { 2818 PetscHashI h; 2819 const PetscInt *points; 2820 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2821 PetscInt pStart, pEnd, part, q; 2822 PetscErrorCode ierr; 2823 2824 PetscFunctionBegin; 2825 PetscHashICreate(h); 2826 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2827 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2828 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2829 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2830 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2831 for(part = pStart; part < pEnd; ++part) { 2832 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2833 2834 PetscHashIClear(h); 2835 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2836 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2837 /* Add all existing points to h */ 2838 for(p = 0; p < numPoints; ++p) { 2839 const PetscInt point = points[off+p]; 2840 PetscHashIAdd(h, point, 1); 2841 } 2842 PetscHashISize(h, nP); 2843 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2844 /* Add all points in next BFS level */ 2845 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2846 for(p = 0; p < numPoints; ++p) { 2847 const PetscInt point = points[off+p]; 2848 PetscInt s = start[point], e = start[point+1], a; 2849 2850 for(a = s; a < e; ++a) { 2851 PetscHashIAdd(h, adjacency[a], 1); 2852 } 2853 } 2854 PetscHashISize(h, numNewPoints); 2855 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2856 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2857 if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2858 totPoints += numNewPoints; 2859 } 2860 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2861 PetscHashIDestroy(h); 2862 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2863 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2864 for(part = pStart, q = 0; part < pEnd; ++part) { 2865 PetscInt numPoints, p; 2866 2867 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2868 for(p = 0; p < numPoints; ++p, ++q) { 2869 newPoints[q] = tmpPoints[part][p]; 2870 } 2871 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2872 } 2873 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2874 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2875 PetscFunctionReturn(0); 2876 } 2877 2878 #undef __FUNCT__ 2879 #define __FUNCT__ "DMPlexCreatePartition" 2880 /* 2881 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2882 2883 Collective on DM 2884 2885 Input Parameters: 2886 + dm - The DM 2887 . height - The height for points in the partition 2888 - enlarge - Expand each partition with neighbors 2889 2890 Output Parameters: 2891 + partSection - The PetscSection giving the division of points by partition 2892 . partition - The list of points by partition 2893 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2894 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2895 2896 Level: developer 2897 2898 .seealso DMPlexDistribute() 2899 */ 2900 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2901 { 2902 PetscMPIInt size; 2903 PetscErrorCode ierr; 2904 2905 PetscFunctionBegin; 2906 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2907 *origPartSection = PETSC_NULL; 2908 *origPartition = PETSC_NULL; 2909 if (size == 1) { 2910 PetscInt *points; 2911 PetscInt cStart, cEnd, c; 2912 2913 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2914 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2915 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2916 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2917 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2918 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2919 for (c = cStart; c < cEnd; ++c) { 2920 points[c] = c; 2921 } 2922 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2923 PetscFunctionReturn(0); 2924 } 2925 if (height == 0) { 2926 PetscInt numVertices; 2927 PetscInt *start = PETSC_NULL; 2928 PetscInt *adjacency = PETSC_NULL; 2929 2930 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2931 if (1) { 2932 #ifdef PETSC_HAVE_CHACO 2933 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2934 #endif 2935 } else { 2936 #ifdef PETSC_HAVE_PARMETIS 2937 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2938 #endif 2939 } 2940 if (enlarge) { 2941 *origPartSection = *partSection; 2942 *origPartition = *partition; 2943 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2944 } 2945 ierr = PetscFree(start);CHKERRQ(ierr); 2946 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2947 # if 0 2948 } else if (height == 1) { 2949 /* Build the dual graph for faces and partition the hypergraph */ 2950 PetscInt numEdges; 2951 2952 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2953 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2954 destroyCSR(numEdges, start, adjacency); 2955 #endif 2956 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2957 PetscFunctionReturn(0); 2958 } 2959 2960 #undef __FUNCT__ 2961 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2962 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2963 { 2964 /* const PetscInt height = 0; */ 2965 const PetscInt *partArray; 2966 PetscInt *allPoints, *partPoints = PETSC_NULL; 2967 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2968 PetscErrorCode ierr; 2969 2970 PetscFunctionBegin; 2971 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2972 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2973 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2974 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2975 for (rank = rStart; rank < rEnd; ++rank) { 2976 PetscInt partSize = 0; 2977 PetscInt numPoints, offset, p; 2978 2979 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2980 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2981 for (p = 0; p < numPoints; ++p) { 2982 PetscInt point = partArray[offset+p], closureSize, c; 2983 PetscInt *closure = PETSC_NULL; 2984 2985 /* TODO Include support for height > 0 case */ 2986 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2987 /* Merge into existing points */ 2988 if (partSize+closureSize > maxPartSize) { 2989 PetscInt *tmpPoints; 2990 2991 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2992 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2993 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2994 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2995 partPoints = tmpPoints; 2996 } 2997 for (c = 0; c < closureSize; ++c) { 2998 partPoints[partSize+c] = closure[c*2]; 2999 } 3000 partSize += closureSize; 3001 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3002 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3003 } 3004 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3005 } 3006 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3007 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3008 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3009 3010 for (rank = rStart; rank < rEnd; ++rank) { 3011 PetscInt partSize = 0, newOffset; 3012 PetscInt numPoints, offset, p; 3013 3014 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3015 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3016 for (p = 0; p < numPoints; ++p) { 3017 PetscInt point = partArray[offset+p], closureSize, c; 3018 PetscInt *closure = PETSC_NULL; 3019 3020 /* TODO Include support for height > 0 case */ 3021 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3022 /* Merge into existing points */ 3023 for (c = 0; c < closureSize; ++c) { 3024 partPoints[partSize+c] = closure[c*2]; 3025 } 3026 partSize += closureSize; 3027 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3028 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3029 } 3030 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3031 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3032 } 3033 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3034 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3035 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3036 PetscFunctionReturn(0); 3037 } 3038 3039 #undef __FUNCT__ 3040 #define __FUNCT__ "DMPlexDistributeField" 3041 /* 3042 Input Parameters: 3043 . originalSection 3044 , originalVec 3045 3046 Output Parameters: 3047 . newSection 3048 . newVec 3049 */ 3050 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3051 { 3052 PetscSF fieldSF; 3053 PetscInt *remoteOffsets, fieldSize; 3054 PetscScalar *originalValues, *newValues; 3055 PetscErrorCode ierr; 3056 3057 PetscFunctionBegin; 3058 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3059 3060 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3061 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3062 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3063 3064 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3065 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3066 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3067 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3068 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3069 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3070 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3071 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3072 PetscFunctionReturn(0); 3073 } 3074 3075 #undef __FUNCT__ 3076 #define __FUNCT__ "DMPlexDistribute" 3077 /*@C 3078 DMPlexDistribute - Distributes the mesh and any associated sections. 3079 3080 Not Collective 3081 3082 Input Parameter: 3083 + dm - The original DMPlex object 3084 . partitioner - The partitioning package, or NULL for the default 3085 - overlap - The overlap of partitions, 0 is the default 3086 3087 Output Parameter: 3088 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3089 3090 Note: If the mesh was not distributed, the return value is PETSC_NULL 3091 3092 Level: intermediate 3093 3094 .keywords: mesh, elements 3095 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3096 @*/ 3097 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3098 { 3099 DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3100 MPI_Comm comm = ((PetscObject) dm)->comm; 3101 const PetscInt height = 0; 3102 PetscInt dim, numRemoteRanks; 3103 IS origCellPart, cellPart, part; 3104 PetscSection origCellPartSection, cellPartSection, partSection; 3105 PetscSFNode *remoteRanks; 3106 PetscSF partSF, pointSF, coneSF; 3107 ISLocalToGlobalMapping renumbering; 3108 PetscSection originalConeSection, newConeSection; 3109 PetscInt *remoteOffsets; 3110 PetscInt *cones, *newCones, newConesSize; 3111 PetscBool flg; 3112 PetscMPIInt rank, numProcs, p; 3113 PetscErrorCode ierr; 3114 3115 PetscFunctionBegin; 3116 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3117 PetscValidPointer(dmParallel,4); 3118 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3119 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3120 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3121 *dmParallel = PETSC_NULL; 3122 if (numProcs == 1) PetscFunctionReturn(0); 3123 3124 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3125 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3126 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3127 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3128 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3129 if (!rank) { 3130 numRemoteRanks = numProcs; 3131 } else { 3132 numRemoteRanks = 0; 3133 } 3134 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3135 for (p = 0; p < numRemoteRanks; ++p) { 3136 remoteRanks[p].rank = p; 3137 remoteRanks[p].index = 0; 3138 } 3139 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3140 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3141 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3142 if (flg) { 3143 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3144 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3145 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3146 if (origCellPart) { 3147 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3148 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3149 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3150 } 3151 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3152 } 3153 /* Close the partition over the mesh */ 3154 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3155 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3156 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3157 /* Create new mesh */ 3158 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3159 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3160 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3161 pmesh = (DM_Plex *) (*dmParallel)->data; 3162 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3163 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3164 if (flg) { 3165 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3166 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3167 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3168 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3169 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3170 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3171 } 3172 /* Distribute cone section */ 3173 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3174 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3175 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3176 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3177 { 3178 PetscInt pStart, pEnd, p; 3179 3180 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3181 for (p = pStart; p < pEnd; ++p) { 3182 PetscInt coneSize; 3183 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3184 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3185 } 3186 } 3187 /* Communicate and renumber cones */ 3188 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3189 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3190 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3191 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3192 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3193 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3194 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3195 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3196 if (flg) { 3197 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3198 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3199 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3200 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3201 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3202 } 3203 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3204 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3205 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3206 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3207 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3208 /* Create supports and stratify sieve */ 3209 { 3210 PetscInt pStart, pEnd; 3211 3212 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3213 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3214 } 3215 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3216 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3217 /* Distribute Coordinates */ 3218 { 3219 PetscSection originalCoordSection, newCoordSection; 3220 Vec originalCoordinates, newCoordinates; 3221 const char *name; 3222 3223 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3224 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3225 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3226 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3227 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3228 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3229 3230 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3231 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3232 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3233 } 3234 /* Distribute labels */ 3235 { 3236 DMLabel next = mesh->labels, newNext = pmesh->labels; 3237 PetscInt numLabels = 0, l; 3238 3239 /* Bcast number of labels */ 3240 while(next) {++numLabels; next = next->next;} 3241 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3242 next = mesh->labels; 3243 for (l = 0; l < numLabels; ++l) { 3244 DMLabel newLabel; 3245 const PetscInt *partArray; 3246 char *name; 3247 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3248 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3249 PetscInt nameSize, s, p; 3250 PetscBool isdepth; 3251 size_t len = 0; 3252 3253 /* Bcast name (could filter for no points) */ 3254 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3255 nameSize = len; 3256 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3257 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3258 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3259 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3260 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3261 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3262 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3263 newLabel->name = name; 3264 /* Bcast numStrata (could filter for no points in stratum) */ 3265 if (!rank) {newLabel->numStrata = next->numStrata;} 3266 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3267 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3268 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3269 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3270 /* Bcast stratumValues (could filter for no points in stratum) */ 3271 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3272 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3273 /* Find size on each process and Scatter */ 3274 if (!rank) { 3275 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3276 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3277 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3278 for (s = 0; s < next->numStrata; ++s) { 3279 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3280 const PetscInt point = next->points[p]; 3281 PetscInt proc; 3282 3283 for (proc = 0; proc < numProcs; ++proc) { 3284 PetscInt dof, off, pPart; 3285 3286 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3287 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3288 for (pPart = off; pPart < off+dof; ++pPart) { 3289 if (partArray[pPart] == point) { 3290 ++stratumSizes[proc*next->numStrata+s]; 3291 break; 3292 } 3293 } 3294 } 3295 } 3296 } 3297 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3298 } 3299 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3300 /* Calculate stratumOffsets */ 3301 newLabel->stratumOffsets[0] = 0; 3302 for (s = 0; s < newLabel->numStrata; ++s) { 3303 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3304 } 3305 /* Pack points and Scatter */ 3306 if (!rank) { 3307 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3308 displs[0] = 0; 3309 for (p = 0; p < numProcs; ++p) { 3310 sendcnts[p] = 0; 3311 for (s = 0; s < next->numStrata; ++s) { 3312 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3313 } 3314 offsets[p] = displs[p]; 3315 displs[p+1] = displs[p] + sendcnts[p]; 3316 } 3317 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3318 for (s = 0; s < next->numStrata; ++s) { 3319 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3320 const PetscInt point = next->points[p]; 3321 PetscInt proc; 3322 3323 for (proc = 0; proc < numProcs; ++proc) { 3324 PetscInt dof, off, pPart; 3325 3326 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3327 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3328 for (pPart = off; pPart < off+dof; ++pPart) { 3329 if (partArray[pPart] == point) { 3330 points[offsets[proc]++] = point; 3331 break; 3332 } 3333 } 3334 } 3335 } 3336 } 3337 } 3338 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3339 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3340 ierr = PetscFree(points);CHKERRQ(ierr); 3341 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3342 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3343 /* Renumber points */ 3344 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3345 /* Sort points */ 3346 for (s = 0; s < newLabel->numStrata; ++s) { 3347 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3348 } 3349 /* Insert into list */ 3350 if (newNext) { 3351 newNext->next = newLabel; 3352 } else { 3353 pmesh->labels = newLabel; 3354 } 3355 newNext = newLabel; 3356 if (!rank) {next = next->next;} 3357 } 3358 } 3359 /* Cleanup Partition */ 3360 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3361 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3362 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3363 ierr = ISDestroy(&part);CHKERRQ(ierr); 3364 /* Create point SF for parallel mesh */ 3365 { 3366 const PetscInt *leaves; 3367 PetscSFNode *remotePoints, *rowners, *lowners; 3368 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3369 PetscInt pStart, pEnd; 3370 3371 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3372 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3373 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3374 for (p=0; p<numRoots; p++) { 3375 rowners[p].rank = -1; 3376 rowners[p].index = -1; 3377 } 3378 if (origCellPart) { 3379 /* Make sure cells in the original partition are not assigned to other procs */ 3380 const PetscInt *origCells; 3381 3382 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3383 for (p = 0; p < numProcs; ++p) { 3384 PetscInt dof, off, d; 3385 3386 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3387 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3388 for(d = off; d < off+dof; ++d) { 3389 rowners[origCells[d]].rank = p; 3390 } 3391 } 3392 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3393 } 3394 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3395 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3396 3397 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3398 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3399 for (p = 0; p < numLeaves; ++p) { 3400 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3401 lowners[p].rank = rank; 3402 lowners[p].index = leaves ? leaves[p] : p; 3403 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3404 lowners[p].rank = -2; 3405 lowners[p].index = -2; 3406 } 3407 } 3408 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3409 rowners[p].rank = -3; 3410 rowners[p].index = -3; 3411 } 3412 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3413 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3414 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3415 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3416 for (p = 0; p < numLeaves; ++p) { 3417 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3418 if (lowners[p].rank != rank) ++numGhostPoints; 3419 } 3420 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3421 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3422 for (p = 0, gp = 0; p < numLeaves; ++p) { 3423 if (lowners[p].rank != rank) { 3424 ghostPoints[gp] = leaves ? leaves[p] : p; 3425 remotePoints[gp].rank = lowners[p].rank; 3426 remotePoints[gp].index = lowners[p].index; 3427 ++gp; 3428 } 3429 } 3430 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3431 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3432 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3433 } 3434 /* Cleanup */ 3435 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3436 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3437 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3438 PetscFunctionReturn(0); 3439 } 3440 3441 #undef __FUNCT__ 3442 #define __FUNCT__ "DMPlexRenumber_Private" 3443 /* 3444 Reasons to renumber: 3445 3446 1) Permute points, e.g. bandwidth reduction (Renumber) 3447 3448 a) Must not mix strata 3449 3450 2) Shift numbers for point insertion (Shift) 3451 3452 a) Want operation brken into parts so that insertion can be interleaved 3453 3454 renumbering - An IS which provides the new numbering 3455 */ 3456 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3457 { 3458 PetscFunctionBegin; 3459 PetscFunctionReturn(0); 3460 } 3461 3462 #undef __FUNCT__ 3463 #define __FUNCT__ "DMPlexShiftPoint_Private" 3464 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3465 { 3466 if (depth < 0) return p; 3467 /* Cells */ if (p < depthEnd[depth]) return p; 3468 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3469 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3470 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3471 } 3472 3473 #undef __FUNCT__ 3474 #define __FUNCT__ "DMPlexShiftSizes_Private" 3475 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3476 { 3477 PetscInt *depthEnd; 3478 PetscInt depth = 0, d, pStart, pEnd, p; 3479 PetscErrorCode ierr; 3480 3481 PetscFunctionBegin; 3482 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3483 if (depth < 0) PetscFunctionReturn(0); 3484 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3485 /* Step 1: Expand chart */ 3486 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3487 for(d = 0; d <= depth; ++d) { 3488 pEnd += depthShift[d]; 3489 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3490 } 3491 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3492 /* Step 2: Set cone and support sizes */ 3493 for(d = 0; d <= depth; ++d) { 3494 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3495 for(p = pStart; p < pEnd; ++p) { 3496 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3497 PetscInt size; 3498 3499 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3500 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3501 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3502 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3503 } 3504 } 3505 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3506 PetscFunctionReturn(0); 3507 } 3508 3509 #undef __FUNCT__ 3510 #define __FUNCT__ "DMPlexShiftPoints_Private" 3511 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3512 { 3513 PetscInt *depthEnd, *newpoints; 3514 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3515 PetscErrorCode ierr; 3516 3517 PetscFunctionBegin; 3518 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3519 if (depth < 0) PetscFunctionReturn(0); 3520 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3521 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3522 for(d = 0; d <= depth; ++d) { 3523 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3524 } 3525 /* Step 5: Set cones and supports */ 3526 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3527 for(p = pStart; p < pEnd; ++p) { 3528 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3529 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3530 3531 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3532 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3533 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3534 for(i = 0; i < size; ++i) { 3535 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3536 } 3537 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3538 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3539 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3540 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3541 for(i = 0; i < size; ++i) { 3542 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3543 } 3544 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3545 } 3546 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3547 PetscFunctionReturn(0); 3548 } 3549 3550 #undef __FUNCT__ 3551 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3552 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3553 { 3554 PetscSection coordSection, newCoordSection; 3555 Vec coordinates; 3556 PetscInt *depthEnd; 3557 PetscInt dim, depth = 0, d, vStart, vEnd, v; 3558 PetscErrorCode ierr; 3559 3560 PetscFunctionBegin; 3561 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3562 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3563 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3564 for(d = 0; d <= depth; ++d) { 3565 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3566 } 3567 /* Step 8: Convert coordinates */ 3568 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3569 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3570 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3571 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3572 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3573 ierr = PetscSectionSetChart(newCoordSection, DMPlexShiftPoint_Private(vStart, depth, depthEnd, depthShift), DMPlexShiftPoint_Private(vEnd, depth, depthEnd, depthShift));CHKERRQ(ierr); 3574 for(v = vStart; v < vEnd; ++v) { 3575 const PetscInt newv = DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift); 3576 ierr = PetscSectionSetDof(newCoordSection, newv, dim);CHKERRQ(ierr); 3577 ierr = PetscSectionSetFieldDof(newCoordSection, newv, 0, dim);CHKERRQ(ierr); 3578 } 3579 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3580 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3581 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3582 ierr = DMSetCoordinatesLocal(dmNew, coordinates);CHKERRQ(ierr); 3583 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3584 PetscFunctionReturn(0); 3585 } 3586 3587 #undef __FUNCT__ 3588 #define __FUNCT__ "DMPlexShiftSF_Private" 3589 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3590 { 3591 PetscInt *depthEnd; 3592 PetscInt depth = 0, d; 3593 PetscSF sfPoint, sfPointNew; 3594 const PetscSFNode *remotePoints; 3595 PetscSFNode *gremotePoints; 3596 const PetscInt *localPoints; 3597 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3598 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3599 PetscMPIInt numProcs; 3600 PetscErrorCode ierr; 3601 3602 PetscFunctionBegin; 3603 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3604 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3605 for(d = 0; d <= depth; ++d) { 3606 totShift += depthShift[d]; 3607 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3608 } 3609 /* Step 9: Convert pointSF */ 3610 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3611 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3612 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3613 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3614 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3615 if (numRoots >= 0) { 3616 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3617 for(l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3618 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3619 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3620 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3621 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3622 for(l = 0; l < numLeaves; ++l) { 3623 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3624 gremotePoints[l].rank = remotePoints[l].rank; 3625 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3626 } 3627 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3628 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3629 } 3630 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3631 PetscFunctionReturn(0); 3632 } 3633 3634 #undef __FUNCT__ 3635 #define __FUNCT__ "DMPlexShiftLabels_Private" 3636 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3637 { 3638 PetscSF sfPoint; 3639 DMLabel vtkLabel, ghostLabel; 3640 PetscInt *depthEnd; 3641 const PetscSFNode *leafRemote; 3642 const PetscInt *leafLocal; 3643 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3644 PetscMPIInt rank; 3645 PetscErrorCode ierr; 3646 3647 PetscFunctionBegin; 3648 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3649 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3650 for(d = 0; d <= depth; ++d) { 3651 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3652 } 3653 /* Step 10: Convert labels */ 3654 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3655 for(l = 0; l < numLabels; ++l) { 3656 DMLabel label, newlabel; 3657 const char *lname; 3658 PetscBool isDepth; 3659 IS valueIS; 3660 const PetscInt *values; 3661 PetscInt numValues, val; 3662 3663 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3664 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3665 if (isDepth) continue; 3666 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3667 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3668 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3669 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3670 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3671 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3672 for(val = 0; val < numValues; ++val) { 3673 IS pointIS; 3674 const PetscInt *points; 3675 PetscInt numPoints, p; 3676 3677 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3678 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3679 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3680 for(p = 0; p < numPoints; ++p) { 3681 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3682 3683 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3684 } 3685 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3686 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3687 } 3688 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3689 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3690 } 3691 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3692 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3693 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3694 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3695 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3696 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3697 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3698 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3699 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3700 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3701 for(l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3702 for(; c < leafLocal[l] && c < cEnd; ++c) { 3703 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3704 } 3705 if (leafLocal[l] >= cEnd) break; 3706 if (leafRemote[l].rank == rank) { 3707 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3708 } else { 3709 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3710 } 3711 } 3712 for(; c < cEnd; ++c) { 3713 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3714 } 3715 if (0) { 3716 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3717 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3718 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3719 } 3720 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3721 for(f = fStart; f < fEnd; ++f) { 3722 PetscInt numCells; 3723 3724 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3725 if (numCells < 2) { 3726 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3727 } else { 3728 const PetscInt *cells = PETSC_NULL; 3729 PetscInt vA, vB; 3730 3731 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3732 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3733 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3734 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3735 } 3736 } 3737 if (0) { 3738 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3739 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3740 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3741 } 3742 PetscFunctionReturn(0); 3743 } 3744 3745 #undef __FUNCT__ 3746 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3747 /*@C 3748 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3749 3750 Collective on dm 3751 3752 Input Parameters: 3753 + dm - The original DM 3754 - labelName - The label specifying the boundary faces (this could be auto-generated) 3755 3756 Output Parameters: 3757 + numGhostCells - The number of ghost cells added to the DM 3758 - dmGhosted - The new DM 3759 3760 Level: developer 3761 3762 .seealso: DMCreate() 3763 */ 3764 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3765 { 3766 DMLabel label; 3767 IS valueIS; 3768 const PetscInt *values; 3769 PetscInt *depthShift; 3770 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3771 PetscErrorCode ierr; 3772 3773 PetscFunctionBegin; 3774 /* Count ghost cells */ 3775 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3776 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3777 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3778 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3779 *numGhostCells = 0; 3780 for(fs = 0; fs < numFS; ++fs) { 3781 PetscInt numBdFaces; 3782 3783 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3784 *numGhostCells += numBdFaces; 3785 } 3786 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3787 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3788 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3789 if (depth >= 0) {depthShift[depth] = *numGhostCells;} 3790 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3791 /* Step 3: Set cone/support sizes for new points */ 3792 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3793 for(c = cEnd; c < cEnd + *numGhostCells; ++c) { 3794 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3795 } 3796 for(fs = 0; fs < numFS; ++fs) { 3797 IS faceIS; 3798 const PetscInt *faces; 3799 PetscInt numFaces, f; 3800 3801 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3802 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3803 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3804 for(f = 0; f < numFaces; ++f) { 3805 PetscInt size; 3806 3807 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3808 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3809 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3810 } 3811 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3812 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3813 } 3814 /* Step 4: Setup ghosted DM */ 3815 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3816 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3817 /* Step 6: Set cones and supports for new points */ 3818 ghostCell = cEnd; 3819 for(fs = 0; fs < numFS; ++fs) { 3820 IS faceIS; 3821 const PetscInt *faces; 3822 PetscInt numFaces, f; 3823 3824 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3825 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3826 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3827 for(f = 0; f < numFaces; ++f, ++ghostCell) { 3828 PetscInt newFace = faces[f] + *numGhostCells; 3829 3830 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3831 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3832 } 3833 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3834 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3835 } 3836 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3837 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3838 /* Step 7: Stratify */ 3839 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3840 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3841 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3842 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3843 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3844 PetscFunctionReturn(0); 3845 } 3846 3847 #undef __FUNCT__ 3848 #define __FUNCT__ "DMPlexConstructGhostCells" 3849 /*@C 3850 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3851 3852 Collective on dm 3853 3854 Input Parameters: 3855 + dm - The original DM 3856 - labelName - The label specifying the boundary faces (this could be auto-generated) 3857 3858 Output Parameters: 3859 + numGhostCells - The number of ghost cells added to the DM 3860 - dmGhosted - The new DM 3861 3862 Level: developer 3863 3864 .seealso: DMCreate() 3865 */ 3866 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3867 { 3868 DM gdm; 3869 PetscInt dim; 3870 PetscErrorCode ierr; 3871 3872 PetscFunctionBegin; 3873 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3874 PetscValidPointer(numGhostCells, 3); 3875 PetscValidPointer(dmGhosted, 4); 3876 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3877 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3878 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3879 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3880 switch(dim) { 3881 case 2: 3882 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3883 break; 3884 default: 3885 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3886 } 3887 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3888 *dmGhosted = gdm; 3889 PetscFunctionReturn(0); 3890 } 3891 3892 #undef __FUNCT__ 3893 #define __FUNCT__ "DMPlexInterpolate_2D" 3894 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 3895 { 3896 DM idm; 3897 DM_Plex *mesh; 3898 PetscHashIJ edgeTable; 3899 PetscInt *off; 3900 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 3901 PetscInt numEdges, firstEdge, edge, e; 3902 PetscErrorCode ierr; 3903 3904 PetscFunctionBegin; 3905 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3906 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3907 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3908 numCells = cEnd - cStart; 3909 numVertices = vEnd - vStart; 3910 firstEdge = numCells + numVertices; 3911 numEdges = 0 ; 3912 /* Count edges using algorithm from CreateNeighborCSR */ 3913 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 3914 if (off) { 3915 PetscInt numCorners = 0; 3916 3917 numEdges = off[numCells]/2; 3918 #if 0 3919 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 3920 numEdges += 3*numCells - off[numCells]; 3921 #else 3922 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 3923 for(c = cStart; c < cEnd; ++c) { 3924 PetscInt coneSize; 3925 3926 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 3927 numCorners += coneSize; 3928 } 3929 numEdges += numCorners - off[numCells]; 3930 #endif 3931 } 3932 #if 0 3933 /* Check Euler characteristic V - E + F = 1 */ 3934 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 3935 #endif 3936 /* Create interpolated mesh */ 3937 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 3938 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 3939 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 3940 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 3941 for (c = 0; c < numCells; ++c) { 3942 PetscInt numCorners; 3943 3944 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 3945 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 3946 } 3947 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 3948 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 3949 } 3950 ierr = DMSetUp(idm);CHKERRQ(ierr); 3951 /* Get edge cones from subsets of cell vertices */ 3952 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 3953 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 3954 3955 for (c = 0, edge = firstEdge; c < numCells; ++c) { 3956 const PetscInt *cellFaces; 3957 PetscInt numCellFaces, faceSize, cf; 3958 3959 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 3960 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 3961 for (cf = 0; cf < numCellFaces; ++cf) { 3962 #if 1 3963 PetscHashIJKey key = {PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]), 3964 PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1])}; 3965 3966 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 3967 if (e < 0) { 3968 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3969 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 3970 e = edge++; 3971 } 3972 #else 3973 PetscBool found = PETSC_FALSE; 3974 3975 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 3976 for (e = firstEdge; e < edge; ++e) { 3977 const PetscInt *cone; 3978 3979 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 3980 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 3981 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 3982 found = PETSC_TRUE; 3983 break; 3984 } 3985 } 3986 if (!found) { 3987 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3988 ++edge; 3989 } 3990 #endif 3991 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 3992 } 3993 } 3994 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 3995 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 3996 ierr = PetscFree(off);CHKERRQ(ierr); 3997 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 3998 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 3999 mesh = (DM_Plex *) (idm)->data; 4000 /* Orient edges */ 4001 for (c = 0; c < numCells; ++c) { 4002 const PetscInt *cone = PETSC_NULL, *cellFaces; 4003 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4004 4005 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4006 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4007 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4008 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4009 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4010 for (cf = 0; cf < numCellFaces; ++cf) { 4011 const PetscInt *econe = PETSC_NULL; 4012 PetscInt esize; 4013 4014 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4015 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4016 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]); 4017 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4018 /* Correctly oriented */ 4019 mesh->coneOrientations[coff+cf] = 0; 4020 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4021 /* Start at index 1, and reverse orientation */ 4022 mesh->coneOrientations[coff+cf] = -(1+1); 4023 } 4024 } 4025 } 4026 *dmInt = idm; 4027 PetscFunctionReturn(0); 4028 } 4029 4030 #undef __FUNCT__ 4031 #define __FUNCT__ "DMPlexInterpolate_3D" 4032 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4033 { 4034 DM idm, fdm; 4035 DM_Plex *mesh; 4036 PetscInt *off; 4037 const PetscInt numCorners = 4; 4038 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4039 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4040 PetscErrorCode ierr; 4041 4042 PetscFunctionBegin; 4043 { 4044 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4045 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4046 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4047 } 4048 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4049 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4050 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4051 numCells = cEnd - cStart; 4052 numVertices = vEnd - vStart; 4053 firstFace = numCells + numVertices; 4054 numFaces = 0 ; 4055 /* Count faces using algorithm from CreateNeighborCSR */ 4056 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4057 if (off) { 4058 numFaces = off[numCells]/2; 4059 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4060 numFaces += 4*numCells - off[numCells]; 4061 } 4062 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4063 firstEdge = firstFace + numFaces; 4064 numEdges = numVertices + numFaces - numCells - 1; 4065 /* Create interpolated mesh */ 4066 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4067 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4068 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4069 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4070 for (c = 0; c < numCells; ++c) { 4071 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4072 } 4073 for (f = firstFace; f < firstFace+numFaces; ++f) { 4074 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4075 } 4076 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4077 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4078 } 4079 ierr = DMSetUp(idm);CHKERRQ(ierr); 4080 /* Get face cones from subsets of cell vertices */ 4081 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4082 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4083 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4084 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4085 for (f = firstFace; f < firstFace+numFaces; ++f) { 4086 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4087 } 4088 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4089 for (c = 0, face = firstFace; c < numCells; ++c) { 4090 const PetscInt *cellFaces; 4091 PetscInt numCellFaces, faceSize, cf; 4092 4093 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4094 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4095 for (cf = 0; cf < numCellFaces; ++cf) { 4096 PetscBool found = PETSC_FALSE; 4097 4098 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4099 for (f = firstFace; f < face; ++f) { 4100 const PetscInt *cone = PETSC_NULL; 4101 4102 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4103 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4104 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4105 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4106 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4107 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4108 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4109 found = PETSC_TRUE; 4110 break; 4111 } 4112 } 4113 if (!found) { 4114 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4115 /* Save the vertices for orientation calculation */ 4116 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4117 ++face; 4118 } 4119 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4120 } 4121 } 4122 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4123 /* Get edge cones from subsets of face vertices */ 4124 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4125 const PetscInt *cellFaces; 4126 PetscInt numCellFaces, faceSize, cf; 4127 4128 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4129 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4130 for (cf = 0; cf < numCellFaces; ++cf) { 4131 PetscBool found = PETSC_FALSE; 4132 4133 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4134 for (e = firstEdge; e < edge; ++e) { 4135 const PetscInt *cone = PETSC_NULL; 4136 4137 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4138 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4139 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4140 found = PETSC_TRUE; 4141 break; 4142 } 4143 } 4144 if (!found) { 4145 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4146 ++edge; 4147 } 4148 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4149 } 4150 } 4151 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4152 ierr = PetscFree(off);CHKERRQ(ierr); 4153 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4154 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4155 mesh = (DM_Plex *) (idm)->data; 4156 /* Orient edges */ 4157 for (f = firstFace; f < firstFace+numFaces; ++f) { 4158 const PetscInt *cone, *cellFaces; 4159 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4160 4161 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4162 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4163 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4164 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4165 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4166 for (cf = 0; cf < numCellFaces; ++cf) { 4167 const PetscInt *econe; 4168 PetscInt esize; 4169 4170 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4171 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4172 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]); 4173 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4174 /* Correctly oriented */ 4175 mesh->coneOrientations[coff+cf] = 0; 4176 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4177 /* Start at index 1, and reverse orientation */ 4178 mesh->coneOrientations[coff+cf] = -(1+1); 4179 } 4180 } 4181 } 4182 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4183 /* Orient faces */ 4184 for (c = 0; c < numCells; ++c) { 4185 const PetscInt *cone, *cellFaces; 4186 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4187 4188 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4189 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4190 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4191 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4192 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4193 for (cf = 0; cf < numCellFaces; ++cf) { 4194 PetscInt *origClosure = PETSC_NULL, *closure; 4195 PetscInt closureSize, i; 4196 4197 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4198 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4199 for (i = 4; i < 7; ++i) { 4200 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); 4201 } 4202 closure = &origClosure[4*2]; 4203 /* Remember that this is the orientation for edges, not vertices */ 4204 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4205 /* Correctly oriented */ 4206 mesh->coneOrientations[coff+cf] = 0; 4207 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4208 /* Shifted by 1 */ 4209 mesh->coneOrientations[coff+cf] = 1; 4210 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4211 /* Shifted by 2 */ 4212 mesh->coneOrientations[coff+cf] = 2; 4213 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4214 /* Start at edge 1, and reverse orientation */ 4215 mesh->coneOrientations[coff+cf] = -(1+1); 4216 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4217 /* Start at index 0, and reverse orientation */ 4218 mesh->coneOrientations[coff+cf] = -(0+1); 4219 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4220 /* Start at index 2, and reverse orientation */ 4221 mesh->coneOrientations[coff+cf] = -(2+1); 4222 } 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); 4223 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4224 } 4225 } 4226 { 4227 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4228 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4229 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4230 } 4231 *dmInt = idm; 4232 PetscFunctionReturn(0); 4233 } 4234 4235 #undef __FUNCT__ 4236 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4237 /* 4238 This takes as input the common mesh generator output, a list of the vertices for each cell 4239 */ 4240 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4241 { 4242 PetscInt *cone, c, p; 4243 PetscErrorCode ierr; 4244 4245 PetscFunctionBegin; 4246 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4247 for (c = 0; c < numCells; ++c) { 4248 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4249 } 4250 ierr = DMSetUp(dm);CHKERRQ(ierr); 4251 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4252 for (c = 0; c < numCells; ++c) { 4253 for (p = 0; p < numCorners; ++p) { 4254 cone[p] = cells[c*numCorners+p]+numCells; 4255 } 4256 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4257 } 4258 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4259 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4260 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4261 PetscFunctionReturn(0); 4262 } 4263 4264 #undef __FUNCT__ 4265 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4266 /* 4267 This takes as input the coordinates for each vertex 4268 */ 4269 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4270 { 4271 PetscSection coordSection; 4272 Vec coordinates; 4273 PetscScalar *coords; 4274 PetscInt coordSize, v, d; 4275 PetscErrorCode ierr; 4276 4277 PetscFunctionBegin; 4278 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4279 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4280 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4281 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4282 for (v = numCells; v < numCells+numVertices; ++v) { 4283 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4284 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4285 } 4286 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4287 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4288 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4289 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4290 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4291 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4292 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4293 for (v = 0; v < numVertices; ++v) { 4294 for (d = 0; d < spaceDim; ++d) { 4295 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4296 } 4297 } 4298 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4299 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4300 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4301 PetscFunctionReturn(0); 4302 } 4303 4304 #undef __FUNCT__ 4305 #define __FUNCT__ "DMPlexCreateFromCellList" 4306 /* 4307 This takes as input the common mesh generator output, a list of the vertices for each cell 4308 */ 4309 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4310 { 4311 PetscErrorCode ierr; 4312 4313 PetscFunctionBegin; 4314 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4315 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4316 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4317 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4318 if (interpolate) { 4319 DM idm; 4320 4321 switch(dim) { 4322 case 2: 4323 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4324 case 3: 4325 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4326 default: 4327 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4328 } 4329 ierr = DMDestroy(dm);CHKERRQ(ierr); 4330 *dm = idm; 4331 } 4332 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4333 PetscFunctionReturn(0); 4334 } 4335 4336 #ifdef PETSC_HAVE_TRIANGLE 4337 #include <triangle.h> 4338 4339 #undef __FUNCT__ 4340 #define __FUNCT__ "InitInput_Triangle" 4341 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4342 { 4343 PetscFunctionBegin; 4344 inputCtx->numberofpoints = 0; 4345 inputCtx->numberofpointattributes = 0; 4346 inputCtx->pointlist = PETSC_NULL; 4347 inputCtx->pointattributelist = PETSC_NULL; 4348 inputCtx->pointmarkerlist = PETSC_NULL; 4349 inputCtx->numberofsegments = 0; 4350 inputCtx->segmentlist = PETSC_NULL; 4351 inputCtx->segmentmarkerlist = PETSC_NULL; 4352 inputCtx->numberoftriangleattributes = 0; 4353 inputCtx->trianglelist = PETSC_NULL; 4354 inputCtx->numberofholes = 0; 4355 inputCtx->holelist = PETSC_NULL; 4356 inputCtx->numberofregions = 0; 4357 inputCtx->regionlist = PETSC_NULL; 4358 PetscFunctionReturn(0); 4359 } 4360 4361 #undef __FUNCT__ 4362 #define __FUNCT__ "InitOutput_Triangle" 4363 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4364 { 4365 PetscFunctionBegin; 4366 outputCtx->numberofpoints = 0; 4367 outputCtx->pointlist = PETSC_NULL; 4368 outputCtx->pointattributelist = PETSC_NULL; 4369 outputCtx->pointmarkerlist = PETSC_NULL; 4370 outputCtx->numberoftriangles = 0; 4371 outputCtx->trianglelist = PETSC_NULL; 4372 outputCtx->triangleattributelist = PETSC_NULL; 4373 outputCtx->neighborlist = PETSC_NULL; 4374 outputCtx->segmentlist = PETSC_NULL; 4375 outputCtx->segmentmarkerlist = PETSC_NULL; 4376 outputCtx->numberofedges = 0; 4377 outputCtx->edgelist = PETSC_NULL; 4378 outputCtx->edgemarkerlist = PETSC_NULL; 4379 PetscFunctionReturn(0); 4380 } 4381 4382 #undef __FUNCT__ 4383 #define __FUNCT__ "FiniOutput_Triangle" 4384 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4385 { 4386 PetscFunctionBegin; 4387 free(outputCtx->pointmarkerlist); 4388 free(outputCtx->edgelist); 4389 free(outputCtx->edgemarkerlist); 4390 free(outputCtx->trianglelist); 4391 free(outputCtx->neighborlist); 4392 PetscFunctionReturn(0); 4393 } 4394 4395 #undef __FUNCT__ 4396 #define __FUNCT__ "DMPlexGenerate_Triangle" 4397 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4398 { 4399 MPI_Comm comm = ((PetscObject) boundary)->comm; 4400 PetscInt dim = 2; 4401 const PetscBool createConvexHull = PETSC_FALSE; 4402 const PetscBool constrained = PETSC_FALSE; 4403 struct triangulateio in; 4404 struct triangulateio out; 4405 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4406 PetscMPIInt rank; 4407 PetscErrorCode ierr; 4408 4409 PetscFunctionBegin; 4410 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4411 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4412 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4413 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4414 in.numberofpoints = vEnd - vStart; 4415 if (in.numberofpoints > 0) { 4416 PetscSection coordSection; 4417 Vec coordinates; 4418 PetscScalar *array; 4419 4420 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4421 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4422 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4423 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4424 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4425 for (v = vStart; v < vEnd; ++v) { 4426 const PetscInt idx = v - vStart; 4427 PetscInt off, d; 4428 4429 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4430 for (d = 0; d < dim; ++d) { 4431 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4432 } 4433 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4434 } 4435 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4436 } 4437 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4438 in.numberofsegments = eEnd - eStart; 4439 if (in.numberofsegments > 0) { 4440 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4441 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4442 for (e = eStart; e < eEnd; ++e) { 4443 const PetscInt idx = e - eStart; 4444 const PetscInt *cone; 4445 4446 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4447 in.segmentlist[idx*2+0] = cone[0] - vStart; 4448 in.segmentlist[idx*2+1] = cone[1] - vStart; 4449 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4450 } 4451 } 4452 #if 0 /* Do not currently support holes */ 4453 PetscReal *holeCoords; 4454 PetscInt h, d; 4455 4456 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4457 if (in.numberofholes > 0) { 4458 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4459 for (h = 0; h < in.numberofholes; ++h) { 4460 for (d = 0; d < dim; ++d) { 4461 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4462 } 4463 } 4464 } 4465 #endif 4466 if (!rank) { 4467 char args[32]; 4468 4469 /* Take away 'Q' for verbose output */ 4470 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4471 if (createConvexHull) { 4472 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4473 } 4474 if (constrained) { 4475 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4476 } 4477 triangulate(args, &in, &out, PETSC_NULL); 4478 } 4479 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4480 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4481 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4482 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4483 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4484 4485 { 4486 const PetscInt numCorners = 3; 4487 const PetscInt numCells = out.numberoftriangles; 4488 const PetscInt numVertices = out.numberofpoints; 4489 const int *cells = out.trianglelist; 4490 const double *meshCoords = out.pointlist; 4491 4492 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4493 /* Set labels */ 4494 for (v = 0; v < numVertices; ++v) { 4495 if (out.pointmarkerlist[v]) { 4496 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4497 } 4498 } 4499 if (interpolate) { 4500 for (e = 0; e < out.numberofedges; e++) { 4501 if (out.edgemarkerlist[e]) { 4502 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4503 const PetscInt *edges; 4504 PetscInt numEdges; 4505 4506 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4507 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4508 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4509 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4510 } 4511 } 4512 } 4513 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4514 } 4515 #if 0 /* Do not currently support holes */ 4516 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4517 #endif 4518 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4519 PetscFunctionReturn(0); 4520 } 4521 4522 #undef __FUNCT__ 4523 #define __FUNCT__ "DMPlexRefine_Triangle" 4524 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4525 { 4526 MPI_Comm comm = ((PetscObject) dm)->comm; 4527 PetscInt dim = 2; 4528 struct triangulateio in; 4529 struct triangulateio out; 4530 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4531 PetscMPIInt rank; 4532 PetscErrorCode ierr; 4533 4534 PetscFunctionBegin; 4535 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4536 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4537 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4538 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4539 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4540 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4541 in.numberofpoints = vEnd - vStart; 4542 if (in.numberofpoints > 0) { 4543 PetscSection coordSection; 4544 Vec coordinates; 4545 PetscScalar *array; 4546 4547 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4548 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4549 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4550 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4551 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4552 for (v = vStart; v < vEnd; ++v) { 4553 const PetscInt idx = v - vStart; 4554 PetscInt off, d; 4555 4556 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4557 for (d = 0; d < dim; ++d) { 4558 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4559 } 4560 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4561 } 4562 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4563 } 4564 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4565 in.numberofcorners = 3; 4566 in.numberoftriangles = cEnd - cStart; 4567 in.trianglearealist = (double *) maxVolumes; 4568 if (in.numberoftriangles > 0) { 4569 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4570 for (c = cStart; c < cEnd; ++c) { 4571 const PetscInt idx = c - cStart; 4572 PetscInt *closure = PETSC_NULL; 4573 PetscInt closureSize; 4574 4575 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4576 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4577 for (v = 0; v < 3; ++v) { 4578 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4579 } 4580 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4581 } 4582 } 4583 /* TODO: Segment markers are missing on input */ 4584 #if 0 /* Do not currently support holes */ 4585 PetscReal *holeCoords; 4586 PetscInt h, d; 4587 4588 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4589 if (in.numberofholes > 0) { 4590 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4591 for (h = 0; h < in.numberofholes; ++h) { 4592 for (d = 0; d < dim; ++d) { 4593 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4594 } 4595 } 4596 } 4597 #endif 4598 if (!rank) { 4599 char args[32]; 4600 4601 /* Take away 'Q' for verbose output */ 4602 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4603 triangulate(args, &in, &out, PETSC_NULL); 4604 } 4605 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4606 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4607 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4608 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4609 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4610 4611 { 4612 const PetscInt numCorners = 3; 4613 const PetscInt numCells = out.numberoftriangles; 4614 const PetscInt numVertices = out.numberofpoints; 4615 const int *cells = out.trianglelist; 4616 const double *meshCoords = out.pointlist; 4617 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4618 4619 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4620 /* Set labels */ 4621 for (v = 0; v < numVertices; ++v) { 4622 if (out.pointmarkerlist[v]) { 4623 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4624 } 4625 } 4626 if (interpolate) { 4627 PetscInt e; 4628 4629 for (e = 0; e < out.numberofedges; e++) { 4630 if (out.edgemarkerlist[e]) { 4631 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4632 const PetscInt *edges; 4633 PetscInt numEdges; 4634 4635 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4636 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4637 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4638 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4639 } 4640 } 4641 } 4642 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4643 } 4644 #if 0 /* Do not currently support holes */ 4645 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4646 #endif 4647 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4648 PetscFunctionReturn(0); 4649 } 4650 #endif 4651 4652 #ifdef PETSC_HAVE_TETGEN 4653 #include <tetgen.h> 4654 #undef __FUNCT__ 4655 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4656 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4657 { 4658 MPI_Comm comm = ((PetscObject) boundary)->comm; 4659 const PetscInt dim = 3; 4660 ::tetgenio in; 4661 ::tetgenio out; 4662 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4663 PetscMPIInt rank; 4664 PetscErrorCode ierr; 4665 4666 PetscFunctionBegin; 4667 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4668 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4669 in.numberofpoints = vEnd - vStart; 4670 if (in.numberofpoints > 0) { 4671 PetscSection coordSection; 4672 Vec coordinates; 4673 PetscScalar *array; 4674 4675 in.pointlist = new double[in.numberofpoints*dim]; 4676 in.pointmarkerlist = new int[in.numberofpoints]; 4677 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4678 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4679 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4680 for (v = vStart; v < vEnd; ++v) { 4681 const PetscInt idx = v - vStart; 4682 PetscInt off, d; 4683 4684 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4685 for (d = 0; d < dim; ++d) { 4686 in.pointlist[idx*dim + d] = array[off+d]; 4687 } 4688 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4689 } 4690 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4691 } 4692 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4693 in.numberoffacets = fEnd - fStart; 4694 if (in.numberoffacets > 0) { 4695 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4696 in.facetmarkerlist = new int[in.numberoffacets]; 4697 for (f = fStart; f < fEnd; ++f) { 4698 const PetscInt idx = f - fStart; 4699 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 4700 4701 in.facetlist[idx].numberofpolygons = 1; 4702 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4703 in.facetlist[idx].numberofholes = 0; 4704 in.facetlist[idx].holelist = NULL; 4705 4706 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4707 for (p = 0; p < numPoints*2; p += 2) { 4708 const PetscInt point = points[p]; 4709 if ((point >= vStart) && (point < vEnd)) { 4710 points[numVertices++] = point; 4711 } 4712 } 4713 4714 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4715 poly->numberofvertices = numVertices; 4716 poly->vertexlist = new int[poly->numberofvertices]; 4717 for (v = 0; v < numVertices; ++v) { 4718 const PetscInt vIdx = points[v] - vStart; 4719 poly->vertexlist[v] = vIdx; 4720 } 4721 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4722 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4723 } 4724 } 4725 if (!rank) { 4726 char args[32]; 4727 4728 /* Take away 'Q' for verbose output */ 4729 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4730 ::tetrahedralize(args, &in, &out); 4731 } 4732 { 4733 const PetscInt numCorners = 4; 4734 const PetscInt numCells = out.numberoftetrahedra; 4735 const PetscInt numVertices = out.numberofpoints; 4736 const int *cells = out.tetrahedronlist; 4737 const double *meshCoords = out.pointlist; 4738 4739 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4740 /* Set labels */ 4741 for (v = 0; v < numVertices; ++v) { 4742 if (out.pointmarkerlist[v]) { 4743 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4744 } 4745 } 4746 if (interpolate) { 4747 PetscInt e; 4748 4749 for (e = 0; e < out.numberofedges; e++) { 4750 if (out.edgemarkerlist[e]) { 4751 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4752 const PetscInt *edges; 4753 PetscInt numEdges; 4754 4755 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4756 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4757 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4758 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4759 } 4760 } 4761 for (f = 0; f < out.numberoftrifaces; f++) { 4762 if (out.trifacemarkerlist[f]) { 4763 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4764 const PetscInt *faces; 4765 PetscInt numFaces; 4766 4767 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4768 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4769 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4770 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4771 } 4772 } 4773 } 4774 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4775 } 4776 PetscFunctionReturn(0); 4777 } 4778 4779 #undef __FUNCT__ 4780 #define __FUNCT__ "DMPlexRefine_Tetgen" 4781 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4782 { 4783 MPI_Comm comm = ((PetscObject) dm)->comm; 4784 const PetscInt dim = 3; 4785 ::tetgenio in; 4786 ::tetgenio out; 4787 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4788 PetscMPIInt rank; 4789 PetscErrorCode ierr; 4790 4791 PetscFunctionBegin; 4792 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4793 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4794 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4795 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4796 in.numberofpoints = vEnd - vStart; 4797 if (in.numberofpoints > 0) { 4798 PetscSection coordSection; 4799 Vec coordinates; 4800 PetscScalar *array; 4801 4802 in.pointlist = new double[in.numberofpoints*dim]; 4803 in.pointmarkerlist = new int[in.numberofpoints]; 4804 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4805 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4806 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4807 for (v = vStart; v < vEnd; ++v) { 4808 const PetscInt idx = v - vStart; 4809 PetscInt off, d; 4810 4811 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4812 for (d = 0; d < dim; ++d) { 4813 in.pointlist[idx*dim + d] = array[off+d]; 4814 } 4815 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4816 } 4817 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4818 } 4819 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4820 in.numberofcorners = 4; 4821 in.numberoftetrahedra = cEnd - cStart; 4822 in.tetrahedronvolumelist = (double *) maxVolumes; 4823 if (in.numberoftetrahedra > 0) { 4824 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 4825 for (c = cStart; c < cEnd; ++c) { 4826 const PetscInt idx = c - cStart; 4827 PetscInt *closure = PETSC_NULL; 4828 PetscInt closureSize; 4829 4830 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4831 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 4832 for (v = 0; v < 4; ++v) { 4833 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 4834 } 4835 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4836 } 4837 } 4838 /* TODO: Put in boundary faces with markers */ 4839 if (!rank) { 4840 char args[32]; 4841 4842 /* Take away 'Q' for verbose output */ 4843 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 4844 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 4845 ::tetrahedralize(args, &in, &out); 4846 } 4847 in.tetrahedronvolumelist = NULL; 4848 4849 { 4850 const PetscInt numCorners = 4; 4851 const PetscInt numCells = out.numberoftetrahedra; 4852 const PetscInt numVertices = out.numberofpoints; 4853 const int *cells = out.tetrahedronlist; 4854 const double *meshCoords = out.pointlist; 4855 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4856 4857 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4858 /* Set labels */ 4859 for (v = 0; v < numVertices; ++v) { 4860 if (out.pointmarkerlist[v]) { 4861 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4862 } 4863 } 4864 if (interpolate) { 4865 PetscInt e, f; 4866 4867 for (e = 0; e < out.numberofedges; e++) { 4868 if (out.edgemarkerlist[e]) { 4869 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4870 const PetscInt *edges; 4871 PetscInt numEdges; 4872 4873 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4874 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4875 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4876 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4877 } 4878 } 4879 for (f = 0; f < out.numberoftrifaces; f++) { 4880 if (out.trifacemarkerlist[f]) { 4881 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4882 const PetscInt *faces; 4883 PetscInt numFaces; 4884 4885 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4886 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4887 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4888 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4889 } 4890 } 4891 } 4892 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4893 } 4894 PetscFunctionReturn(0); 4895 } 4896 #endif 4897 4898 #ifdef PETSC_HAVE_CTETGEN 4899 #include "ctetgen.h" 4900 4901 #undef __FUNCT__ 4902 #define __FUNCT__ "DMPlexGenerate_CTetgen" 4903 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 4904 { 4905 MPI_Comm comm = ((PetscObject) boundary)->comm; 4906 const PetscInt dim = 3; 4907 PLC *in, *out; 4908 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 4909 PetscMPIInt rank; 4910 PetscErrorCode ierr; 4911 4912 PetscFunctionBegin; 4913 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 4914 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4915 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4916 ierr = PLCCreate(&in);CHKERRQ(ierr); 4917 ierr = PLCCreate(&out);CHKERRQ(ierr); 4918 in->numberofpoints = vEnd - vStart; 4919 if (in->numberofpoints > 0) { 4920 PetscSection coordSection; 4921 Vec coordinates; 4922 PetscScalar *array; 4923 4924 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 4925 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 4926 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4927 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4928 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4929 for (v = vStart; v < vEnd; ++v) { 4930 const PetscInt idx = v - vStart; 4931 PetscInt off, d, m; 4932 4933 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4934 for (d = 0; d < dim; ++d) { 4935 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4936 } 4937 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 4938 in->pointmarkerlist[idx] = (int) m; 4939 } 4940 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4941 } 4942 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4943 in->numberoffacets = fEnd - fStart; 4944 if (in->numberoffacets > 0) { 4945 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 4946 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 4947 for (f = fStart; f < fEnd; ++f) { 4948 const PetscInt idx = f - fStart; 4949 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 4950 polygon *poly; 4951 4952 in->facetlist[idx].numberofpolygons = 1; 4953 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 4954 in->facetlist[idx].numberofholes = 0; 4955 in->facetlist[idx].holelist = PETSC_NULL; 4956 4957 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4958 for (p = 0; p < numPoints*2; p += 2) { 4959 const PetscInt point = points[p]; 4960 if ((point >= vStart) && (point < vEnd)) { 4961 points[numVertices++] = point; 4962 } 4963 } 4964 4965 poly = in->facetlist[idx].polygonlist; 4966 poly->numberofvertices = numVertices; 4967 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 4968 for (v = 0; v < numVertices; ++v) { 4969 const PetscInt vIdx = points[v] - vStart; 4970 poly->vertexlist[v] = vIdx; 4971 } 4972 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 4973 in->facetmarkerlist[idx] = (int) m; 4974 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4975 } 4976 } 4977 if (!rank) { 4978 TetGenOpts t; 4979 4980 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 4981 t.in = boundary; /* Should go away */ 4982 t.plc = 1; 4983 t.quality = 1; 4984 t.edgesout = 1; 4985 t.zeroindex = 1; 4986 t.quiet = 1; 4987 t.verbose = verbose; 4988 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 4989 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 4990 } 4991 { 4992 const PetscInt numCorners = 4; 4993 const PetscInt numCells = out->numberoftetrahedra; 4994 const PetscInt numVertices = out->numberofpoints; 4995 const int *cells = out->tetrahedronlist; 4996 const double *meshCoords = out->pointlist; 4997 4998 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4999 /* Set labels */ 5000 for (v = 0; v < numVertices; ++v) { 5001 if (out->pointmarkerlist[v]) { 5002 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5003 } 5004 } 5005 if (interpolate) { 5006 PetscInt e; 5007 5008 for (e = 0; e < out->numberofedges; e++) { 5009 if (out->edgemarkerlist[e]) { 5010 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5011 const PetscInt *edges; 5012 PetscInt numEdges; 5013 5014 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5015 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5016 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5017 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5018 } 5019 } 5020 for (f = 0; f < out->numberoftrifaces; f++) { 5021 if (out->trifacemarkerlist[f]) { 5022 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5023 const PetscInt *faces; 5024 PetscInt numFaces; 5025 5026 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5027 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5028 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5029 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5030 } 5031 } 5032 } 5033 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5034 } 5035 5036 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5037 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5038 PetscFunctionReturn(0); 5039 } 5040 5041 #undef __FUNCT__ 5042 #define __FUNCT__ "DMPlexRefine_CTetgen" 5043 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5044 { 5045 MPI_Comm comm = ((PetscObject) dm)->comm; 5046 const PetscInt dim = 3; 5047 PLC *in, *out; 5048 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5049 PetscMPIInt rank; 5050 PetscErrorCode ierr; 5051 5052 PetscFunctionBegin; 5053 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5054 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5055 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5056 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5057 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5058 ierr = PLCCreate(&in);CHKERRQ(ierr); 5059 ierr = PLCCreate(&out);CHKERRQ(ierr); 5060 in->numberofpoints = vEnd - vStart; 5061 if (in->numberofpoints > 0) { 5062 PetscSection coordSection; 5063 Vec coordinates; 5064 PetscScalar *array; 5065 5066 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5067 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5068 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5069 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5070 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5071 for (v = vStart; v < vEnd; ++v) { 5072 const PetscInt idx = v - vStart; 5073 PetscInt off, d, m; 5074 5075 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5076 for (d = 0; d < dim; ++d) { 5077 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5078 } 5079 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5080 in->pointmarkerlist[idx] = (int) m; 5081 } 5082 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5083 } 5084 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5085 in->numberofcorners = 4; 5086 in->numberoftetrahedra = cEnd - cStart; 5087 in->tetrahedronvolumelist = maxVolumes; 5088 if (in->numberoftetrahedra > 0) { 5089 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5090 for (c = cStart; c < cEnd; ++c) { 5091 const PetscInt idx = c - cStart; 5092 PetscInt *closure = PETSC_NULL; 5093 PetscInt closureSize; 5094 5095 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5096 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5097 for (v = 0; v < 4; ++v) { 5098 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5099 } 5100 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5101 } 5102 } 5103 if (!rank) { 5104 TetGenOpts t; 5105 5106 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5107 t.in = dm; /* Should go away */ 5108 t.refine = 1; 5109 t.varvolume = 1; 5110 t.quality = 1; 5111 t.edgesout = 1; 5112 t.zeroindex = 1; 5113 t.quiet = 1; 5114 t.verbose = verbose; /* Change this */ 5115 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5116 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5117 } 5118 { 5119 const PetscInt numCorners = 4; 5120 const PetscInt numCells = out->numberoftetrahedra; 5121 const PetscInt numVertices = out->numberofpoints; 5122 const int *cells = out->tetrahedronlist; 5123 const double *meshCoords = out->pointlist; 5124 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5125 5126 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5127 /* Set labels */ 5128 for (v = 0; v < numVertices; ++v) { 5129 if (out->pointmarkerlist[v]) { 5130 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5131 } 5132 } 5133 if (interpolate) { 5134 PetscInt e, f; 5135 5136 for (e = 0; e < out->numberofedges; e++) { 5137 if (out->edgemarkerlist[e]) { 5138 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5139 const PetscInt *edges; 5140 PetscInt numEdges; 5141 5142 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5143 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5144 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5145 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5146 } 5147 } 5148 for (f = 0; f < out->numberoftrifaces; f++) { 5149 if (out->trifacemarkerlist[f]) { 5150 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5151 const PetscInt *faces; 5152 PetscInt numFaces; 5153 5154 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5155 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5156 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5157 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5158 } 5159 } 5160 } 5161 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5162 } 5163 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5164 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5165 PetscFunctionReturn(0); 5166 } 5167 #endif 5168 5169 #undef __FUNCT__ 5170 #define __FUNCT__ "DMPlexGenerate" 5171 /*@C 5172 DMPlexGenerate - Generates a mesh. 5173 5174 Not Collective 5175 5176 Input Parameters: 5177 + boundary - The DMPlex boundary object 5178 . name - The mesh generation package name 5179 - interpolate - Flag to create intermediate mesh elements 5180 5181 Output Parameter: 5182 . mesh - The DMPlex object 5183 5184 Level: intermediate 5185 5186 .keywords: mesh, elements 5187 .seealso: DMPlexCreate(), DMRefine() 5188 @*/ 5189 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5190 { 5191 PetscInt dim; 5192 char genname[1024]; 5193 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5194 PetscErrorCode ierr; 5195 5196 PetscFunctionBegin; 5197 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5198 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5199 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5200 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5201 if (flg) {name = genname;} 5202 if (name) { 5203 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5204 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5205 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5206 } 5207 switch(dim) { 5208 case 1: 5209 if (!name || isTriangle) { 5210 #ifdef PETSC_HAVE_TRIANGLE 5211 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5212 #else 5213 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5214 #endif 5215 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5216 break; 5217 case 2: 5218 if (!name || isCTetgen) { 5219 #ifdef PETSC_HAVE_CTETGEN 5220 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5221 #else 5222 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5223 #endif 5224 } else if (isTetgen) { 5225 #ifdef PETSC_HAVE_TETGEN 5226 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5227 #else 5228 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5229 #endif 5230 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5231 break; 5232 default: 5233 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5234 } 5235 PetscFunctionReturn(0); 5236 } 5237 5238 typedef PetscInt CellRefiner; 5239 5240 #undef __FUNCT__ 5241 #define __FUNCT__ "GetDepthStart_Private" 5242 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5243 { 5244 PetscFunctionBegin; 5245 if (cStart) *cStart = 0; 5246 if (vStart) *vStart = depthSize[depth]; 5247 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5248 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5249 PetscFunctionReturn(0); 5250 } 5251 5252 #undef __FUNCT__ 5253 #define __FUNCT__ "GetDepthEnd_Private" 5254 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5255 { 5256 PetscFunctionBegin; 5257 if (cEnd) *cEnd = depthSize[depth]; 5258 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5259 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5260 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5261 PetscFunctionReturn(0); 5262 } 5263 5264 #undef __FUNCT__ 5265 #define __FUNCT__ "CellRefinerGetSizes" 5266 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5267 { 5268 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5269 PetscErrorCode ierr; 5270 5271 PetscFunctionBegin; 5272 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5273 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5274 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5275 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5276 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5277 switch(refiner) { 5278 case 1: 5279 /* Simplicial 2D */ 5280 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5281 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5282 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5283 break; 5284 case 3: 5285 /* Hybrid 2D */ 5286 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5287 cMax = PetscMin(cEnd, cMax); 5288 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5289 fMax = PetscMin(fEnd, fMax); 5290 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5291 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 */ 5292 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5293 break; 5294 case 2: 5295 /* Hex 2D */ 5296 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5297 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5298 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5299 break; 5300 default: 5301 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5302 } 5303 PetscFunctionReturn(0); 5304 } 5305 5306 #undef __FUNCT__ 5307 #define __FUNCT__ "CellRefinerSetConeSizes" 5308 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5309 { 5310 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5311 PetscErrorCode ierr; 5312 5313 PetscFunctionBegin; 5314 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5315 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5316 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5317 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5318 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5319 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5320 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5321 switch(refiner) { 5322 case 1: 5323 /* Simplicial 2D */ 5324 /* All cells have 3 faces */ 5325 for(c = cStart; c < cEnd; ++c) { 5326 for(r = 0; r < 4; ++r) { 5327 const PetscInt newp = (c - cStart)*4 + r; 5328 5329 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5330 } 5331 } 5332 /* Split faces have 2 vertices and the same cells as the parent */ 5333 for(f = fStart; f < fEnd; ++f) { 5334 for(r = 0; r < 2; ++r) { 5335 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5336 PetscInt size; 5337 5338 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5339 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5340 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5341 } 5342 } 5343 /* Interior faces have 2 vertices and 2 cells */ 5344 for(c = cStart; c < cEnd; ++c) { 5345 for(r = 0; r < 3; ++r) { 5346 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5347 5348 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5349 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5350 } 5351 } 5352 /* Old vertices have identical supports */ 5353 for(v = vStart; v < vEnd; ++v) { 5354 const PetscInt newp = vStartNew + (v - vStart); 5355 PetscInt size; 5356 5357 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5358 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5359 } 5360 /* Face vertices have 2 + cells*2 supports */ 5361 for(f = fStart; f < fEnd; ++f) { 5362 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5363 PetscInt size; 5364 5365 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5366 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5367 } 5368 break; 5369 case 2: 5370 /* Hex 2D */ 5371 /* All cells have 4 faces */ 5372 for(c = cStart; c < cEnd; ++c) { 5373 for(r = 0; r < 4; ++r) { 5374 const PetscInt newp = (c - cStart)*4 + r; 5375 5376 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5377 } 5378 } 5379 /* Split faces have 2 vertices and the same cells as the parent */ 5380 for(f = fStart; f < fEnd; ++f) { 5381 for(r = 0; r < 2; ++r) { 5382 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5383 PetscInt size; 5384 5385 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5386 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5387 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5388 } 5389 } 5390 /* Interior faces have 2 vertices and 2 cells */ 5391 for(c = cStart; c < cEnd; ++c) { 5392 for(r = 0; r < 4; ++r) { 5393 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5394 5395 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5396 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5397 } 5398 } 5399 /* Old vertices have identical supports */ 5400 for(v = vStart; v < vEnd; ++v) { 5401 const PetscInt newp = vStartNew + (v - vStart); 5402 PetscInt size; 5403 5404 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5405 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5406 } 5407 /* Face vertices have 2 + cells supports */ 5408 for(f = fStart; f < fEnd; ++f) { 5409 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5410 PetscInt size; 5411 5412 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5413 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5414 } 5415 /* Cell vertices have 4 supports */ 5416 for(c = cStart; c < cEnd; ++c) { 5417 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5418 5419 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5420 } 5421 break; 5422 case 3: 5423 /* Hybrid 2D */ 5424 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5425 cMax = PetscMin(cEnd, cMax); 5426 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5427 fMax = PetscMin(fEnd, fMax); 5428 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5429 /* Interior cells have 3 faces */ 5430 for(c = cStart; c < cMax; ++c) { 5431 for(r = 0; r < 4; ++r) { 5432 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5433 5434 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5435 } 5436 } 5437 /* Hybrid cells have 4 faces */ 5438 for(c = cMax; c < cEnd; ++c) { 5439 for(r = 0; r < 2; ++r) { 5440 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5441 5442 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5443 } 5444 } 5445 /* Interior split faces have 2 vertices and the same cells as the parent */ 5446 for(f = fStart; f < fMax; ++f) { 5447 for(r = 0; r < 2; ++r) { 5448 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5449 PetscInt size; 5450 5451 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5452 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5453 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5454 } 5455 } 5456 /* Interior cell faces have 2 vertices and 2 cells */ 5457 for(c = cStart; c < cMax; ++c) { 5458 for(r = 0; r < 3; ++r) { 5459 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5460 5461 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5462 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5463 } 5464 } 5465 /* Hybrid faces have 2 vertices and the same cells */ 5466 for(f = fMax; f < fEnd; ++f) { 5467 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5468 PetscInt size; 5469 5470 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5471 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5472 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5473 } 5474 /* Hybrid cell faces have 2 vertices and 2 cells */ 5475 for(c = cMax; c < cEnd; ++c) { 5476 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5477 5478 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5479 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5480 } 5481 /* Old vertices have identical supports */ 5482 for(v = vStart; v < vEnd; ++v) { 5483 const PetscInt newp = vStartNew + (v - vStart); 5484 PetscInt size; 5485 5486 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5487 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5488 } 5489 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5490 for(f = fStart; f < fMax; ++f) { 5491 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5492 const PetscInt *support; 5493 PetscInt size, newSize = 2, s; 5494 5495 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5496 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5497 for(s = 0; s < size; ++s) { 5498 if (support[s] >= cMax) { 5499 newSize += 1; 5500 } else { 5501 newSize += 2; 5502 } 5503 } 5504 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5505 } 5506 break; 5507 default: 5508 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5509 } 5510 PetscFunctionReturn(0); 5511 } 5512 5513 #undef __FUNCT__ 5514 #define __FUNCT__ "CellRefinerSetCones" 5515 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5516 { 5517 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; 5518 PetscInt maxSupportSize, *supportRef; 5519 PetscErrorCode ierr; 5520 5521 PetscFunctionBegin; 5522 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5523 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5524 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5525 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5526 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5527 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5528 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5529 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5530 switch(refiner) { 5531 case 1: 5532 /* Simplicial 2D */ 5533 /* 5534 2 5535 |\ 5536 | \ 5537 | \ 5538 | \ 5539 | C \ 5540 | \ 5541 | \ 5542 2---1---1 5543 |\ D / \ 5544 | 2 0 \ 5545 |A \ / B \ 5546 0---0-------1 5547 */ 5548 /* All cells have 3 faces */ 5549 for(c = cStart; c < cEnd; ++c) { 5550 const PetscInt newp = cStartNew + (c - cStart)*4; 5551 const PetscInt *cone, *ornt; 5552 PetscInt coneNew[3], orntNew[3]; 5553 5554 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5555 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5556 /* A triangle */ 5557 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5558 orntNew[0] = ornt[0]; 5559 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5560 orntNew[1] = -2; 5561 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5562 orntNew[2] = ornt[2]; 5563 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5564 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5565 #if 1 5566 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); 5567 for(p = 0; p < 3; ++p) { 5568 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); 5569 } 5570 #endif 5571 /* B triangle */ 5572 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5573 orntNew[0] = ornt[0]; 5574 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5575 orntNew[1] = ornt[1]; 5576 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5577 orntNew[2] = -2; 5578 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5579 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5580 #if 1 5581 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); 5582 for(p = 0; p < 3; ++p) { 5583 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); 5584 } 5585 #endif 5586 /* C triangle */ 5587 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5588 orntNew[0] = -2; 5589 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5590 orntNew[1] = ornt[1]; 5591 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5592 orntNew[2] = ornt[2]; 5593 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5594 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5595 #if 1 5596 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); 5597 for(p = 0; p < 3; ++p) { 5598 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); 5599 } 5600 #endif 5601 /* D triangle */ 5602 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5603 orntNew[0] = 0; 5604 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5605 orntNew[1] = 0; 5606 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5607 orntNew[2] = 0; 5608 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5609 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5610 #if 1 5611 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); 5612 for(p = 0; p < 3; ++p) { 5613 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); 5614 } 5615 #endif 5616 } 5617 /* Split faces have 2 vertices and the same cells as the parent */ 5618 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5619 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5620 for(f = fStart; f < fEnd; ++f) { 5621 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5622 5623 for(r = 0; r < 2; ++r) { 5624 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5625 const PetscInt *cone, *support; 5626 PetscInt coneNew[2], coneSize, c, supportSize, s; 5627 5628 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5629 coneNew[0] = vStartNew + (cone[0] - vStart); 5630 coneNew[1] = vStartNew + (cone[1] - vStart); 5631 coneNew[(r+1)%2] = newv; 5632 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5633 #if 1 5634 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5635 for(p = 0; p < 2; ++p) { 5636 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); 5637 } 5638 #endif 5639 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5640 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5641 for(s = 0; s < supportSize; ++s) { 5642 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5643 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5644 for(c = 0; c < coneSize; ++c) { 5645 if (cone[c] == f) { 5646 break; 5647 } 5648 } 5649 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5650 } 5651 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5652 #if 1 5653 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5654 for(p = 0; p < supportSize; ++p) { 5655 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); 5656 } 5657 #endif 5658 } 5659 } 5660 /* Interior faces have 2 vertices and 2 cells */ 5661 for(c = cStart; c < cEnd; ++c) { 5662 const PetscInt *cone; 5663 5664 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5665 for(r = 0; r < 3; ++r) { 5666 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5667 PetscInt coneNew[2]; 5668 PetscInt supportNew[2]; 5669 5670 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5671 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5672 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5673 #if 1 5674 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5675 for(p = 0; p < 2; ++p) { 5676 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); 5677 } 5678 #endif 5679 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5680 supportNew[1] = (c - cStart)*4 + 3; 5681 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5682 #if 1 5683 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5684 for(p = 0; p < 2; ++p) { 5685 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); 5686 } 5687 #endif 5688 } 5689 } 5690 /* Old vertices have identical supports */ 5691 for(v = vStart; v < vEnd; ++v) { 5692 const PetscInt newp = vStartNew + (v - vStart); 5693 const PetscInt *support, *cone; 5694 PetscInt size, s; 5695 5696 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5697 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5698 for(s = 0; s < size; ++s) { 5699 PetscInt r = 0; 5700 5701 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5702 if (cone[1] == v) r = 1; 5703 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5704 } 5705 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5706 #if 1 5707 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5708 for(p = 0; p < size; ++p) { 5709 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); 5710 } 5711 #endif 5712 } 5713 /* Face vertices have 2 + cells*2 supports */ 5714 for(f = fStart; f < fEnd; ++f) { 5715 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5716 const PetscInt *cone, *support; 5717 PetscInt size, s; 5718 5719 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5720 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5721 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5722 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5723 for(s = 0; s < size; ++s) { 5724 PetscInt r = 0; 5725 5726 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5727 if (cone[1] == f) r = 1; 5728 else if (cone[2] == f) r = 2; 5729 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5730 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5731 } 5732 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5733 #if 1 5734 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5735 for(p = 0; p < 2+size*2; ++p) { 5736 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); 5737 } 5738 #endif 5739 } 5740 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5741 break; 5742 case 2: 5743 /* Hex 2D */ 5744 /* 5745 3---------2---------2 5746 | | | 5747 | D 2 C | 5748 | | | 5749 3----3----0----1----1 5750 | | | 5751 | A 0 B | 5752 | | | 5753 0---------0---------1 5754 */ 5755 /* All cells have 4 faces */ 5756 for(c = cStart; c < cEnd; ++c) { 5757 const PetscInt newp = (c - cStart)*4; 5758 const PetscInt *cone, *ornt; 5759 PetscInt coneNew[4], orntNew[4]; 5760 5761 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5762 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5763 /* A quad */ 5764 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5765 orntNew[0] = ornt[0]; 5766 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5767 orntNew[1] = 0; 5768 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5769 orntNew[2] = -2; 5770 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5771 orntNew[3] = ornt[3]; 5772 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5773 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5774 #if 1 5775 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); 5776 for(p = 0; p < 4; ++p) { 5777 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); 5778 } 5779 #endif 5780 /* B quad */ 5781 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5782 orntNew[0] = ornt[0]; 5783 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5784 orntNew[1] = ornt[1]; 5785 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5786 orntNew[2] = 0; 5787 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5788 orntNew[3] = -2; 5789 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5790 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5791 #if 1 5792 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); 5793 for(p = 0; p < 4; ++p) { 5794 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); 5795 } 5796 #endif 5797 /* C quad */ 5798 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5799 orntNew[0] = -2; 5800 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5801 orntNew[1] = ornt[1]; 5802 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5803 orntNew[2] = ornt[2]; 5804 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5805 orntNew[3] = 0; 5806 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5807 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5808 #if 1 5809 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); 5810 for(p = 0; p < 4; ++p) { 5811 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); 5812 } 5813 #endif 5814 /* D quad */ 5815 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5816 orntNew[0] = 0; 5817 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5818 orntNew[1] = -2; 5819 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5820 orntNew[2] = ornt[2]; 5821 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 5822 orntNew[3] = ornt[3]; 5823 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5824 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5825 #if 1 5826 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); 5827 for(p = 0; p < 4; ++p) { 5828 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); 5829 } 5830 #endif 5831 } 5832 /* Split faces have 2 vertices and the same cells as the parent */ 5833 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5834 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5835 for(f = fStart; f < fEnd; ++f) { 5836 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5837 5838 for(r = 0; r < 2; ++r) { 5839 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5840 const PetscInt *cone, *support; 5841 PetscInt coneNew[2], coneSize, c, supportSize, s; 5842 5843 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5844 coneNew[0] = vStartNew + (cone[0] - vStart); 5845 coneNew[1] = vStartNew + (cone[1] - vStart); 5846 coneNew[(r+1)%2] = newv; 5847 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5848 #if 1 5849 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5850 for(p = 0; p < 2; ++p) { 5851 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); 5852 } 5853 #endif 5854 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5855 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5856 for(s = 0; s < supportSize; ++s) { 5857 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5858 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5859 for(c = 0; c < coneSize; ++c) { 5860 if (cone[c] == f) { 5861 break; 5862 } 5863 } 5864 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 5865 } 5866 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5867 #if 1 5868 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5869 for(p = 0; p < supportSize; ++p) { 5870 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); 5871 } 5872 #endif 5873 } 5874 } 5875 /* Interior faces have 2 vertices and 2 cells */ 5876 for(c = cStart; c < cEnd; ++c) { 5877 const PetscInt *cone; 5878 PetscInt coneNew[2], supportNew[2]; 5879 5880 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5881 for(r = 0; r < 4; ++r) { 5882 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5883 5884 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5885 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5886 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5887 #if 1 5888 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5889 for(p = 0; p < 2; ++p) { 5890 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); 5891 } 5892 #endif 5893 supportNew[0] = (c - cStart)*4 + r; 5894 supportNew[1] = (c - cStart)*4 + (r+1)%4; 5895 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5896 #if 1 5897 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5898 for(p = 0; p < 2; ++p) { 5899 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); 5900 } 5901 #endif 5902 } 5903 } 5904 /* Old vertices have identical supports */ 5905 for(v = vStart; v < vEnd; ++v) { 5906 const PetscInt newp = vStartNew + (v - vStart); 5907 const PetscInt *support, *cone; 5908 PetscInt size, s; 5909 5910 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5911 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5912 for(s = 0; s < size; ++s) { 5913 PetscInt r = 0; 5914 5915 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5916 if (cone[1] == v) r = 1; 5917 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5918 } 5919 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5920 #if 1 5921 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5922 for(p = 0; p < size; ++p) { 5923 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); 5924 } 5925 #endif 5926 } 5927 /* Face vertices have 2 + cells supports */ 5928 for(f = fStart; f < fEnd; ++f) { 5929 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5930 const PetscInt *cone, *support; 5931 PetscInt size, s; 5932 5933 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5934 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5935 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5936 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5937 for(s = 0; s < size; ++s) { 5938 PetscInt r = 0; 5939 5940 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5941 if (cone[1] == f) r = 1; 5942 else if (cone[2] == f) r = 2; 5943 else if (cone[3] == f) r = 3; 5944 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 5945 } 5946 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5947 #if 1 5948 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5949 for(p = 0; p < 2+size; ++p) { 5950 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); 5951 } 5952 #endif 5953 } 5954 /* Cell vertices have 4 supports */ 5955 for(c = cStart; c < cEnd; ++c) { 5956 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5957 PetscInt supportNew[4]; 5958 5959 for(r = 0; r < 4; ++r) { 5960 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5961 } 5962 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5963 } 5964 break; 5965 case 3: 5966 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5967 cMax = PetscMin(cEnd, cMax); 5968 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5969 fMax = PetscMin(fEnd, fMax); 5970 /* Interior cells have 3 faces */ 5971 for(c = cStart; c < cMax; ++c) { 5972 const PetscInt newp = cStartNew + (c - cStart)*4; 5973 const PetscInt *cone, *ornt; 5974 PetscInt coneNew[3], orntNew[3]; 5975 5976 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5977 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5978 /* A triangle */ 5979 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5980 orntNew[0] = ornt[0]; 5981 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 5982 orntNew[1] = -2; 5983 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5984 orntNew[2] = ornt[2]; 5985 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5986 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5987 #if 1 5988 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); 5989 for(p = 0; p < 3; ++p) { 5990 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); 5991 } 5992 #endif 5993 /* B triangle */ 5994 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5995 orntNew[0] = ornt[0]; 5996 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5997 orntNew[1] = ornt[1]; 5998 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 5999 orntNew[2] = -2; 6000 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6001 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6002 #if 1 6003 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); 6004 for(p = 0; p < 3; ++p) { 6005 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); 6006 } 6007 #endif 6008 /* C triangle */ 6009 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6010 orntNew[0] = -2; 6011 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6012 orntNew[1] = ornt[1]; 6013 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6014 orntNew[2] = ornt[2]; 6015 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6016 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6017 #if 1 6018 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); 6019 for(p = 0; p < 3; ++p) { 6020 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); 6021 } 6022 #endif 6023 /* D triangle */ 6024 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6025 orntNew[0] = 0; 6026 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6027 orntNew[1] = 0; 6028 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6029 orntNew[2] = 0; 6030 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6031 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6032 #if 1 6033 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); 6034 for(p = 0; p < 3; ++p) { 6035 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); 6036 } 6037 #endif 6038 } 6039 /* 6040 2----3----3 6041 | | 6042 | B | 6043 | | 6044 0----4--- 1 6045 | | 6046 | A | 6047 | | 6048 0----2----1 6049 */ 6050 /* Hybrid cells have 4 faces */ 6051 for(c = cMax; c < cEnd; ++c) { 6052 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6053 const PetscInt *cone, *ornt; 6054 PetscInt coneNew[4], orntNew[4]; 6055 6056 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6057 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6058 /* A quad */ 6059 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6060 orntNew[0] = ornt[0]; 6061 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6062 orntNew[1] = ornt[1]; 6063 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6064 orntNew[2] = 0; 6065 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6066 orntNew[3] = 0; 6067 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6068 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6069 #if 1 6070 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); 6071 for(p = 0; p < 4; ++p) { 6072 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); 6073 } 6074 #endif 6075 /* B quad */ 6076 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6077 orntNew[0] = ornt[0]; 6078 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6079 orntNew[1] = ornt[1]; 6080 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6081 orntNew[2] = 0; 6082 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6083 orntNew[3] = 0; 6084 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6085 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6086 #if 1 6087 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); 6088 for(p = 0; p < 4; ++p) { 6089 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); 6090 } 6091 #endif 6092 } 6093 /* Interior split faces have 2 vertices and the same cells as the parent */ 6094 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6095 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6096 for(f = fStart; f < fMax; ++f) { 6097 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6098 6099 for(r = 0; r < 2; ++r) { 6100 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6101 const PetscInt *cone, *support; 6102 PetscInt coneNew[2], coneSize, c, supportSize, s; 6103 6104 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6105 coneNew[0] = vStartNew + (cone[0] - vStart); 6106 coneNew[1] = vStartNew + (cone[1] - vStart); 6107 coneNew[(r+1)%2] = newv; 6108 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6109 #if 1 6110 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6111 for(p = 0; p < 2; ++p) { 6112 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); 6113 } 6114 #endif 6115 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6116 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6117 for(s = 0; s < supportSize; ++s) { 6118 if (support[s] >= cMax) { 6119 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6120 } else { 6121 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6122 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6123 for(c = 0; c < coneSize; ++c) { 6124 if (cone[c] == f) { 6125 break; 6126 } 6127 } 6128 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6129 } 6130 } 6131 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6132 #if 1 6133 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6134 for(p = 0; p < supportSize; ++p) { 6135 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); 6136 } 6137 #endif 6138 } 6139 } 6140 /* Interior cell faces have 2 vertices and 2 cells */ 6141 for(c = cStart; c < cMax; ++c) { 6142 const PetscInt *cone; 6143 6144 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6145 for(r = 0; r < 3; ++r) { 6146 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6147 PetscInt coneNew[2]; 6148 PetscInt supportNew[2]; 6149 6150 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6151 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6152 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6153 #if 1 6154 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6155 for(p = 0; p < 2; ++p) { 6156 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); 6157 } 6158 #endif 6159 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6160 supportNew[1] = (c - cStart)*4 + 3; 6161 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6162 #if 1 6163 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6164 for(p = 0; p < 2; ++p) { 6165 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); 6166 } 6167 #endif 6168 } 6169 } 6170 /* Interior hybrid faces have 2 vertices and the same cells */ 6171 for(f = fMax; f < fEnd; ++f) { 6172 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6173 const PetscInt *cone; 6174 const PetscInt *support; 6175 PetscInt coneNew[2]; 6176 PetscInt supportNew[2]; 6177 PetscInt size, s, r; 6178 6179 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6180 coneNew[0] = vStartNew + (cone[0] - vStart); 6181 coneNew[1] = vStartNew + (cone[1] - vStart); 6182 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6183 #if 1 6184 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6185 for(p = 0; p < 2; ++p) { 6186 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); 6187 } 6188 #endif 6189 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6190 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6191 for(s = 0; s < size; ++s) { 6192 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6193 for(r = 0; r < 2; ++r) { 6194 if (cone[r+2] == f) break; 6195 } 6196 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6197 } 6198 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6199 #if 1 6200 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6201 for(p = 0; p < size; ++p) { 6202 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); 6203 } 6204 #endif 6205 } 6206 /* Cell hybrid faces have 2 vertices and 2 cells */ 6207 for(c = cMax; c < cEnd; ++c) { 6208 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6209 const PetscInt *cone; 6210 PetscInt coneNew[2]; 6211 PetscInt supportNew[2]; 6212 6213 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6214 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6215 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6216 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6217 #if 1 6218 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6219 for(p = 0; p < 2; ++p) { 6220 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); 6221 } 6222 #endif 6223 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6224 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6225 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6226 #if 1 6227 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6228 for(p = 0; p < 2; ++p) { 6229 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); 6230 } 6231 #endif 6232 } 6233 /* Old vertices have identical supports */ 6234 for(v = vStart; v < vEnd; ++v) { 6235 const PetscInt newp = vStartNew + (v - vStart); 6236 const PetscInt *support, *cone; 6237 PetscInt size, s; 6238 6239 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6240 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6241 for(s = 0; s < size; ++s) { 6242 if (support[s] >= fMax) { 6243 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6244 } else { 6245 PetscInt r = 0; 6246 6247 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6248 if (cone[1] == v) r = 1; 6249 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6250 } 6251 } 6252 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6253 #if 1 6254 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6255 for(p = 0; p < size; ++p) { 6256 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); 6257 } 6258 #endif 6259 } 6260 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6261 for(f = fStart; f < fMax; ++f) { 6262 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6263 const PetscInt *cone, *support; 6264 PetscInt size, newSize = 2, s; 6265 6266 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6267 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6268 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6269 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6270 for(s = 0; s < size; ++s) { 6271 PetscInt r = 0; 6272 6273 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6274 if (support[s] >= cMax) { 6275 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6276 newSize += 1; 6277 } else { 6278 if (cone[1] == f) r = 1; 6279 else if (cone[2] == f) r = 2; 6280 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6281 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6282 newSize += 2; 6283 } 6284 } 6285 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6286 #if 1 6287 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6288 for(p = 0; p < newSize; ++p) { 6289 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); 6290 } 6291 #endif 6292 } 6293 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6294 break; 6295 default: 6296 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6297 } 6298 PetscFunctionReturn(0); 6299 } 6300 6301 #undef __FUNCT__ 6302 #define __FUNCT__ "CellRefinerSetCoordinates" 6303 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6304 { 6305 PetscSection coordSection, coordSectionNew; 6306 Vec coordinates, coordinatesNew; 6307 PetscScalar *coords, *coordsNew; 6308 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6309 PetscErrorCode ierr; 6310 6311 PetscFunctionBegin; 6312 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6313 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6314 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6315 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6316 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6317 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6318 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6319 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6320 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6321 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6322 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6323 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6324 if (fMax < 0) fMax = fEnd; 6325 switch(refiner) { 6326 case 1: 6327 case 2: 6328 case 3: 6329 /* Simplicial and Hex 2D */ 6330 /* All vertices have the dim coordinates */ 6331 for(v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6332 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6333 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6334 } 6335 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6336 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6337 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6338 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6339 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6340 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6341 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6342 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6343 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6344 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6345 /* Old vertices have the same coordinates */ 6346 for(v = vStart; v < vEnd; ++v) { 6347 const PetscInt newv = vStartNew + (v - vStart); 6348 PetscInt off, offnew, d; 6349 6350 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6351 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6352 for(d = 0; d < dim; ++d) { 6353 coordsNew[offnew+d] = coords[off+d]; 6354 } 6355 } 6356 /* Face vertices have the average of endpoint coordinates */ 6357 for(f = fStart; f < fMax; ++f) { 6358 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6359 const PetscInt *cone; 6360 PetscInt coneSize, offA, offB, offnew, d; 6361 6362 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6363 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6364 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6365 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6366 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6367 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6368 for(d = 0; d < dim; ++d) { 6369 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6370 } 6371 } 6372 /* Just Hex 2D */ 6373 if (refiner == 2) { 6374 /* Cell vertices have the average of corner coordinates */ 6375 for(c = cStart; c < cEnd; ++c) { 6376 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6377 PetscInt *cone = PETSC_NULL; 6378 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6379 6380 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6381 for(p = 0; p < closureSize*2; p += 2) { 6382 const PetscInt point = cone[p]; 6383 if ((point >= vStart) && (point < vEnd)) { 6384 cone[coneSize++] = point; 6385 } 6386 } 6387 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6388 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6389 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6390 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6391 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6392 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6393 for(d = 0; d < dim; ++d) { 6394 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6395 } 6396 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6397 } 6398 } 6399 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6400 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6401 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6402 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6403 break; 6404 default: 6405 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6406 } 6407 PetscFunctionReturn(0); 6408 } 6409 6410 #undef __FUNCT__ 6411 #define __FUNCT__ "DMPlexCreateProcessSF" 6412 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6413 { 6414 PetscInt numRoots, numLeaves, l; 6415 const PetscInt *localPoints; 6416 const PetscSFNode *remotePoints; 6417 PetscInt *localPointsNew; 6418 PetscSFNode *remotePointsNew; 6419 PetscInt *ranks, *ranksNew; 6420 PetscErrorCode ierr; 6421 6422 PetscFunctionBegin; 6423 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6424 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6425 for(l = 0; l < numLeaves; ++l) { 6426 ranks[l] = remotePoints[l].rank; 6427 } 6428 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6429 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6430 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6431 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6432 for(l = 0; l < numLeaves; ++l) { 6433 ranksNew[l] = ranks[l]; 6434 localPointsNew[l] = l; 6435 remotePointsNew[l].index = 0; 6436 remotePointsNew[l].rank = ranksNew[l]; 6437 } 6438 ierr = PetscFree(ranks);CHKERRQ(ierr); 6439 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6440 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6441 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6442 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6443 PetscFunctionReturn(0); 6444 } 6445 6446 #undef __FUNCT__ 6447 #define __FUNCT__ "CellRefinerCreateSF" 6448 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6449 { 6450 PetscSF sf, sfNew, sfProcess; 6451 IS processRanks; 6452 MPI_Datatype depthType; 6453 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6454 const PetscInt *localPoints, *neighbors; 6455 const PetscSFNode *remotePoints; 6456 PetscInt *localPointsNew; 6457 PetscSFNode *remotePointsNew; 6458 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6459 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6460 PetscErrorCode ierr; 6461 6462 PetscFunctionBegin; 6463 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6464 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6465 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6466 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6467 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6468 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6469 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6470 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6471 switch(refiner) { 6472 case 3: 6473 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6474 cMax = PetscMin(cEnd, cMax); 6475 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6476 fMax = PetscMin(fEnd, fMax); 6477 } 6478 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6479 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6480 /* Caculate size of new SF */ 6481 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6482 if (numRoots < 0) PetscFunctionReturn(0); 6483 for(l = 0; l < numLeaves; ++l) { 6484 const PetscInt p = localPoints[l]; 6485 6486 switch(refiner) { 6487 case 1: 6488 /* Simplicial 2D */ 6489 if ((p >= vStart) && (p < vEnd)) { 6490 /* Old vertices stay the same */ 6491 ++numLeavesNew; 6492 } else if ((p >= fStart) && (p < fEnd)) { 6493 /* Old faces add new faces and vertex */ 6494 numLeavesNew += 1 + 2; 6495 } else if ((p >= cStart) && (p < cEnd)) { 6496 /* Old cells add new cells and interior faces */ 6497 numLeavesNew += 4 + 3; 6498 } 6499 break; 6500 case 2: 6501 /* Hex 2D */ 6502 if ((p >= vStart) && (p < vEnd)) { 6503 /* Old vertices stay the same */ 6504 ++numLeavesNew; 6505 } else if ((p >= fStart) && (p < fEnd)) { 6506 /* Old faces add new faces and vertex */ 6507 numLeavesNew += 1 + 2; 6508 } else if ((p >= cStart) && (p < cEnd)) { 6509 /* Old cells add new cells and interior faces */ 6510 numLeavesNew += 4 + 4; 6511 } 6512 break; 6513 default: 6514 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6515 } 6516 } 6517 /* Communicate depthSizes for each remote rank */ 6518 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6519 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6520 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6521 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); 6522 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6523 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6524 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6525 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6526 for(n = 0; n < numNeighbors; ++n) { 6527 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6528 } 6529 depthSizeOld[depth] = cMax; 6530 depthSizeOld[0] = vMax; 6531 depthSizeOld[depth-1] = fMax; 6532 depthSizeOld[1] = eMax; 6533 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6534 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6535 depthSizeOld[depth] = cEnd - cStart; 6536 depthSizeOld[0] = vEnd - vStart; 6537 depthSizeOld[depth-1] = fEnd - fStart; 6538 depthSizeOld[1] = eEnd - eStart; 6539 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6540 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6541 for(n = 0; n < numNeighbors; ++n) { 6542 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6543 } 6544 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6545 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6546 /* Calculate new point SF */ 6547 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6548 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6549 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6550 for(l = 0, m = 0; l < numLeaves; ++l) { 6551 PetscInt p = localPoints[l]; 6552 PetscInt rp = remotePoints[l].index, n; 6553 PetscMPIInt rrank = remotePoints[l].rank; 6554 6555 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6556 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6557 switch(refiner) { 6558 case 1: 6559 /* Simplicial 2D */ 6560 if ((p >= vStart) && (p < vEnd)) { 6561 /* Old vertices stay the same */ 6562 localPointsNew[m] = vStartNew + (p - vStart); 6563 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6564 remotePointsNew[m].rank = rrank; 6565 ++m; 6566 } else if ((p >= fStart) && (p < fEnd)) { 6567 /* Old faces add new faces and vertex */ 6568 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6569 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6570 remotePointsNew[m].rank = rrank; 6571 ++m; 6572 for(r = 0; r < 2; ++r, ++m) { 6573 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6574 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6575 remotePointsNew[m].rank = rrank; 6576 } 6577 } else if ((p >= cStart) && (p < cEnd)) { 6578 /* Old cells add new cells and interior faces */ 6579 for(r = 0; r < 4; ++r, ++m) { 6580 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6581 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6582 remotePointsNew[m].rank = rrank; 6583 } 6584 for(r = 0; r < 3; ++r, ++m) { 6585 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6586 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6587 remotePointsNew[m].rank = rrank; 6588 } 6589 } 6590 break; 6591 case 2: 6592 /* Hex 2D */ 6593 if ((p >= vStart) && (p < vEnd)) { 6594 /* Old vertices stay the same */ 6595 localPointsNew[m] = vStartNew + (p - vStart); 6596 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6597 remotePointsNew[m].rank = rrank; 6598 ++m; 6599 } else if ((p >= fStart) && (p < fEnd)) { 6600 /* Old faces add new faces and vertex */ 6601 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6602 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6603 remotePointsNew[m].rank = rrank; 6604 ++m; 6605 for(r = 0; r < 2; ++r, ++m) { 6606 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6607 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6608 remotePointsNew[m].rank = rrank; 6609 } 6610 } else if ((p >= cStart) && (p < cEnd)) { 6611 /* Old cells add new cells and interior faces */ 6612 for(r = 0; r < 4; ++r, ++m) { 6613 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6614 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6615 remotePointsNew[m].rank = rrank; 6616 } 6617 for(r = 0; r < 4; ++r, ++m) { 6618 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6619 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6620 remotePointsNew[m].rank = rrank; 6621 } 6622 } 6623 break; 6624 case 3: 6625 /* Hybrid simplicial 2D */ 6626 if ((p >= vStart) && (p < vEnd)) { 6627 /* Old vertices stay the same */ 6628 localPointsNew[m] = vStartNew + (p - vStart); 6629 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6630 remotePointsNew[m].rank = rrank; 6631 ++m; 6632 } else if ((p >= fStart) && (p < fMax)) { 6633 /* Old interior faces add new faces and vertex */ 6634 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6635 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6636 remotePointsNew[m].rank = rrank; 6637 ++m; 6638 for(r = 0; r < 2; ++r, ++m) { 6639 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6640 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6641 remotePointsNew[m].rank = rrank; 6642 } 6643 } else if ((p >= fMax) && (p < fEnd)) { 6644 /* Old hybrid faces stay the same */ 6645 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6646 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6647 remotePointsNew[m].rank = rrank; 6648 ++m; 6649 } else if ((p >= cStart) && (p < cMax)) { 6650 /* Old interior cells add new cells and interior faces */ 6651 for(r = 0; r < 4; ++r, ++m) { 6652 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6653 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6654 remotePointsNew[m].rank = rrank; 6655 } 6656 for(r = 0; r < 3; ++r, ++m) { 6657 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6658 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6659 remotePointsNew[m].rank = rrank; 6660 } 6661 } else if ((p >= cStart) && (p < cMax)) { 6662 /* Old hybrid cells add new cells and hybrid face */ 6663 for(r = 0; r < 2; ++r, ++m) { 6664 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6665 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6666 remotePointsNew[m].rank = rrank; 6667 } 6668 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6669 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]); 6670 remotePointsNew[m].rank = rrank; 6671 ++m; 6672 } 6673 break; 6674 default: 6675 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6676 } 6677 } 6678 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6679 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6680 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6681 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6682 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6683 PetscFunctionReturn(0); 6684 } 6685 6686 #undef __FUNCT__ 6687 #define __FUNCT__ "CellRefinerCreateLabels" 6688 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6689 { 6690 PetscInt numLabels, l; 6691 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6692 PetscErrorCode ierr; 6693 6694 PetscFunctionBegin; 6695 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6696 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6697 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6698 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6699 cStartNew = 0; 6700 vStartNew = depthSize[2]; 6701 fStartNew = depthSize[2] + depthSize[0]; 6702 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6703 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6704 switch(refiner) { 6705 case 3: 6706 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6707 cMax = PetscMin(cEnd, cMax); 6708 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6709 fMax = PetscMin(fEnd, fMax); 6710 } 6711 for(l = 0; l < numLabels; ++l) { 6712 DMLabel label, labelNew; 6713 const char *lname; 6714 PetscBool isDepth; 6715 IS valueIS; 6716 const PetscInt *values; 6717 PetscInt numValues, val; 6718 6719 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6720 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6721 if (isDepth) continue; 6722 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6723 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6724 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6725 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6726 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6727 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6728 for(val = 0; val < numValues; ++val) { 6729 IS pointIS; 6730 const PetscInt *points; 6731 PetscInt numPoints, n; 6732 6733 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6734 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6735 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6736 for(n = 0; n < numPoints; ++n) { 6737 const PetscInt p = points[n]; 6738 switch(refiner) { 6739 case 1: 6740 /* Simplicial 2D */ 6741 if ((p >= vStart) && (p < vEnd)) { 6742 /* Old vertices stay the same */ 6743 newp = vStartNew + (p - vStart); 6744 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6745 } else if ((p >= fStart) && (p < fEnd)) { 6746 /* Old faces add new faces and vertex */ 6747 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6748 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6749 for(r = 0; r < 2; ++r) { 6750 newp = fStartNew + (p - fStart)*2 + r; 6751 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6752 } 6753 } else if ((p >= cStart) && (p < cEnd)) { 6754 /* Old cells add new cells and interior faces */ 6755 for(r = 0; r < 4; ++r) { 6756 newp = cStartNew + (p - cStart)*4 + r; 6757 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6758 } 6759 for(r = 0; r < 3; ++r) { 6760 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6761 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6762 } 6763 } 6764 break; 6765 case 2: 6766 /* Hex 2D */ 6767 if ((p >= vStart) && (p < vEnd)) { 6768 /* Old vertices stay the same */ 6769 newp = vStartNew + (p - vStart); 6770 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6771 } else if ((p >= fStart) && (p < fEnd)) { 6772 /* Old faces add new faces and vertex */ 6773 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6774 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6775 for(r = 0; r < 2; ++r) { 6776 newp = fStartNew + (p - fStart)*2 + r; 6777 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6778 } 6779 } else if ((p >= cStart) && (p < cEnd)) { 6780 /* Old cells add new cells and interior faces and vertex */ 6781 for(r = 0; r < 4; ++r) { 6782 newp = cStartNew + (p - cStart)*4 + r; 6783 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6784 } 6785 for(r = 0; r < 4; ++r) { 6786 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6787 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6788 } 6789 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 6790 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6791 } 6792 break; 6793 case 3: 6794 /* Hybrid simplicial 2D */ 6795 if ((p >= vStart) && (p < vEnd)) { 6796 /* Old vertices stay the same */ 6797 newp = vStartNew + (p - vStart); 6798 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6799 } else if ((p >= fStart) && (p < fMax)) { 6800 /* Old interior faces add new faces and vertex */ 6801 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6802 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6803 for(r = 0; r < 2; ++r) { 6804 newp = fStartNew + (p - fStart)*2 + r; 6805 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6806 } 6807 } else if ((p >= fMax) && (p < fEnd)) { 6808 /* Old hybrid faces stay the same */ 6809 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 6810 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6811 } else if ((p >= cStart) && (p < cMax)) { 6812 /* Old interior cells add new cells and interior faces */ 6813 for(r = 0; r < 4; ++r) { 6814 newp = cStartNew + (p - cStart)*4 + r; 6815 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6816 } 6817 for(r = 0; r < 3; ++r) { 6818 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6819 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6820 } 6821 } else if ((p >= cMax) && (p < cEnd)) { 6822 /* Old hybrid cells add new cells and hybrid face */ 6823 for(r = 0; r < 2; ++r) { 6824 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 6825 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6826 } 6827 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6828 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6829 } 6830 break; 6831 default: 6832 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6833 } 6834 } 6835 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 6836 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 6837 } 6838 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 6839 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 6840 if (0) { 6841 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 6842 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6843 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6844 } 6845 } 6846 PetscFunctionReturn(0); 6847 } 6848 6849 #undef __FUNCT__ 6850 #define __FUNCT__ "DMPlexRefine_Uniform" 6851 /* This will only work for interpolated meshes */ 6852 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 6853 { 6854 DM rdm; 6855 PetscInt *depthSize; 6856 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 6857 PetscErrorCode ierr; 6858 6859 PetscFunctionBegin; 6860 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 6861 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 6862 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6863 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 6864 /* Calculate number of new points of each depth */ 6865 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6866 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 6867 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 6868 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 6869 /* Step 1: Set chart */ 6870 for(d = 0; d <= depth; ++d) { 6871 pEnd += depthSize[d]; 6872 } 6873 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 6874 /* Step 2: Set cone/support sizes */ 6875 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6876 /* Step 3: Setup refined DM */ 6877 ierr = DMSetUp(rdm);CHKERRQ(ierr); 6878 /* Step 4: Set cones and supports */ 6879 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6880 /* Step 5: Stratify */ 6881 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 6882 /* Step 6: Set coordinates for vertices */ 6883 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6884 /* Step 7: Create pointSF */ 6885 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6886 /* Step 8: Create labels */ 6887 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6888 ierr = PetscFree(depthSize);CHKERRQ(ierr); 6889 6890 *dmRefined = rdm; 6891 #if 0 6892 DM_Plex *mesh = (DM_Plex *) dm->data; 6893 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 6894 /* ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); */ 6895 6896 PetscFunctionBegin; 6897 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6898 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 6899 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6900 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6901 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 6902 6903 /* Count number of new cells which are normal and extra */ 6904 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 6905 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 6906 for(c = cStart; c < cEnd2; ++c) { 6907 PetscInt n; 6908 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 6909 newNumCellsNormal += n; 6910 } 6911 for(c = cEnd2; c < cEnd; ++c) { 6912 PetscInt n; 6913 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 6914 newNumCellsExtra += n; 6915 } 6916 newNumCells = newNumCellsNormal + newNumCellsExtra; 6917 /* Count number of new vertices which are normal and extra */ 6918 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 6919 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 6920 for(c = cStart; c < cEnd; ++c) { 6921 PetscInt *closure = PETSC_NULL; 6922 PetscInt closureSize, numCorners = 0, p; 6923 6924 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6925 for(p = 0; p < closureSize*2; p += 2) { 6926 const PetscInt point = closure[p]; 6927 if ((point >= vStart) && (point < vEnd)) { 6928 closure[numCorners++] = point; 6929 } 6930 } 6931 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCell */ 6932 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6933 } 6934 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 6935 for(c = cEnd2; c < cEnd; ++c) { 6936 PetscInt *closure = PETSC_NULL; 6937 PetscInt closureSize, numCorners = 0, p; 6938 6939 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6940 for(p = 0; p < closureSize*2; p += 2) { 6941 const PetscInt point = closure[p]; 6942 if ((point >= vStart) && (point < vEnd)) { 6943 closure[numCorners++] = point; 6944 } 6945 } 6946 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCellUncensored */ 6947 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6948 } /* for */ 6949 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 6950 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 6951 6952 #if 1 6953 PetscInt oldNumCellsNormal = cEnd2 - cStart; 6954 PetscInt oldNumCellsExtra = cEnd - cEnd2; 6955 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 6956 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 6957 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 6958 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 6959 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 6960 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 6961 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 6962 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 6963 ierr = PetscSynchronizedFlush(comm); 6964 #endif 6965 6966 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 6967 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 6968 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 6969 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 6970 ierr = DMPlexGetHybridBounds(*dmRefined, newNumCellsNormal, PETSC_NULL, PETSC_NULL, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 6971 /* Set cone and support sizes for new normal cells */ 6972 PetscInt newCell = 0; 6973 for(c = cStart; c < cEnd2; ++c) { 6974 PetscInt coneSize, n, i; 6975 6976 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6977 ierr = CellRefinerGetNumSubcells(refiner, c, &n); /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 6978 for(i = 0; i < n; ++i, ++newCell) { 6979 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 6980 } 6981 6982 PetscInt *closure = PETSC_NULL; 6983 PetscInt closureSize, numCorners = 0, p; 6984 6985 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6986 for(p = 0; p < closureSize*2; p += 2) { 6987 const PetscInt point = closure[p]; 6988 if ((point >= vStart) && (point < vEnd)) { 6989 closure[numCorners++] = point; 6990 } 6991 } 6992 /* ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 6993 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6994 } 6995 6996 /* Reset current new cell value and loop over censored cells. */ 6997 curNewCell = _orderNewMesh->cellsCensored().min(); 6998 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 6999 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7000 /* Set new cone and support sizes */ 7001 cV.clear(); 7002 sieve->cone(*c_iter, cV); 7003 const point_type* cone = cV.getPoints(); 7004 const int coneSize = cV.getSize(); 7005 7006 const point_type* newCells; 7007 int numNewCells = 0; 7008 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7009 7010 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7011 newSieve->setConeSize(curNewCell, coneSize); 7012 for(int iVertex=0; iVertex < coneSize; ++iVertex) { 7013 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 7014 } /* for */ 7015 } /* for */ 7016 } /* for */ 7017 newSieve->allocate(); 7018 7019 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 7020 7021 /* Create refined cells in new sieve. */ 7022 curNewCell = _orderNewMesh->cellsNormal().min(); 7023 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 7024 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 7025 cV.clear(); 7026 sieve->cone(*c_iter, cV); 7027 const point_type *cone = cV.getPoints(); 7028 const int coneSize = cV.getSize(); 7029 7030 const point_type* newCells; 7031 int numNewCells = 0; 7032 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7033 7034 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7035 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7036 } /* for */ 7037 } /* for */ 7038 curNewCell = _orderNewMesh->cellsCensored().min(); 7039 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7040 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7041 cV.clear(); 7042 sieve->cone(*c_iter, cV); 7043 const point_type *cone = cV.getPoints(); 7044 const int coneSize = cV.getSize(); 7045 7046 const point_type* newCells; 7047 int numNewCells = 0; 7048 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7049 7050 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7051 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7052 } /* for */ 7053 } /* for */ 7054 newSieve->symmetrize(); 7055 7056 /* Set coordinates in refined mesh. */ 7057 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 7058 assert(!coordinates.isNull()); 7059 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 7060 assert(!newCoordinates.isNull()); 7061 7062 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 7063 assert(vertices->size() > 0); 7064 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 7065 assert(spaceDim > 0); 7066 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 7067 7068 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 7069 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 7070 newCoordinates->setFiberDimension(*v_iter, spaceDim); 7071 } /* for */ 7072 newCoordinates->allocatePoint(); 7073 7074 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 7075 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7076 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7077 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7078 } /* for */ 7079 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 7080 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7081 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7082 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7083 } /* for */ 7084 7085 refiner.setCoordsNewVertices(newCoordinates, coordinates); 7086 7087 /* Create sensored depth */ 7088 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 7089 assert(!censoredLabel.isNull()); 7090 7091 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 7092 7093 newSieve->roots(depthVisitor); 7094 while(depthVisitor.isModified()) { 7095 /* FIX: Avoid the copy here somehow by fixing the traversal */ 7096 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 7097 7098 depthVisitor.clear(); 7099 newSieve->support(modifiedPoints, depthVisitor); 7100 } /* while */ 7101 /* Stratify refined mesh */ 7102 /* Calculate new point SF */ 7103 _calcNewOverlap(newMesh, mesh, refiner); 7104 /* Calculate new labels */ 7105 _createLabels(newMesh, mesh, refiner); 7106 #endif 7107 PetscFunctionReturn(0); 7108 } 7109 7110 #undef __FUNCT__ 7111 #define __FUNCT__ "DMPlexSetRefinementUniform" 7112 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7113 { 7114 DM_Plex *mesh = (DM_Plex *) dm->data; 7115 7116 PetscFunctionBegin; 7117 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7118 mesh->refinementUniform = refinementUniform; 7119 PetscFunctionReturn(0); 7120 } 7121 7122 #undef __FUNCT__ 7123 #define __FUNCT__ "DMPlexGetRefinementUniform" 7124 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7125 { 7126 DM_Plex *mesh = (DM_Plex *) dm->data; 7127 7128 PetscFunctionBegin; 7129 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7130 PetscValidPointer(refinementUniform, 2); 7131 *refinementUniform = mesh->refinementUniform; 7132 PetscFunctionReturn(0); 7133 } 7134 7135 #undef __FUNCT__ 7136 #define __FUNCT__ "DMPlexSetRefinementLimit" 7137 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7138 { 7139 DM_Plex *mesh = (DM_Plex *) dm->data; 7140 7141 PetscFunctionBegin; 7142 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7143 mesh->refinementLimit = refinementLimit; 7144 PetscFunctionReturn(0); 7145 } 7146 7147 #undef __FUNCT__ 7148 #define __FUNCT__ "DMPlexGetRefinementLimit" 7149 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7150 { 7151 DM_Plex *mesh = (DM_Plex *) dm->data; 7152 7153 PetscFunctionBegin; 7154 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7155 PetscValidPointer(refinementLimit, 2); 7156 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7157 *refinementLimit = mesh->refinementLimit; 7158 PetscFunctionReturn(0); 7159 } 7160 7161 #undef __FUNCT__ 7162 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7163 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7164 { 7165 PetscInt dim, cStart, coneSize, cMax; 7166 PetscErrorCode ierr; 7167 7168 PetscFunctionBegin; 7169 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7170 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7171 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7172 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7173 switch(dim) { 7174 case 2: 7175 switch(coneSize) { 7176 case 3: 7177 if (cMax >= 0) { 7178 *cellRefiner = 3; /* Hybrid */ 7179 } else { 7180 *cellRefiner = 1; /* Triangular */ 7181 } 7182 break; 7183 case 4: 7184 if (cMax >= 0) { 7185 *cellRefiner = 4; /* Hybrid */ 7186 } else { 7187 *cellRefiner = 2; /* Quadrilateral */ 7188 } 7189 break; 7190 default: 7191 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7192 } 7193 break; 7194 default: 7195 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7196 } 7197 PetscFunctionReturn(0); 7198 } 7199 7200 #undef __FUNCT__ 7201 #define __FUNCT__ "DMRefine_Plex" 7202 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7203 { 7204 PetscReal refinementLimit; 7205 PetscInt dim, cStart, cEnd; 7206 char genname[1024], *name = PETSC_NULL; 7207 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7208 PetscErrorCode ierr; 7209 7210 PetscFunctionBegin; 7211 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7212 if (isUniform) { 7213 CellRefiner cellRefiner; 7214 7215 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7216 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7217 PetscFunctionReturn(0); 7218 } 7219 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7220 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7221 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7222 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7223 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7224 if (flg) {name = genname;} 7225 if (name) { 7226 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7227 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7228 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7229 } 7230 switch(dim) { 7231 case 2: 7232 if (!name || isTriangle) { 7233 #ifdef PETSC_HAVE_TRIANGLE 7234 double *maxVolumes; 7235 PetscInt c; 7236 7237 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7238 for (c = 0; c < cEnd-cStart; ++c) { 7239 maxVolumes[c] = refinementLimit; 7240 } 7241 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7242 #else 7243 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7244 #endif 7245 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7246 break; 7247 case 3: 7248 if (!name || isCTetgen) { 7249 #ifdef PETSC_HAVE_CTETGEN 7250 PetscReal *maxVolumes; 7251 PetscInt c; 7252 7253 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7254 for (c = 0; c < cEnd-cStart; ++c) { 7255 maxVolumes[c] = refinementLimit; 7256 } 7257 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7258 #else 7259 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7260 #endif 7261 } else if (isTetgen) { 7262 #ifdef PETSC_HAVE_TETGEN 7263 double *maxVolumes; 7264 PetscInt c; 7265 7266 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7267 for (c = 0; c < cEnd-cStart; ++c) { 7268 maxVolumes[c] = refinementLimit; 7269 } 7270 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7271 #else 7272 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7273 #endif 7274 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7275 break; 7276 default: 7277 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7278 } 7279 PetscFunctionReturn(0); 7280 } 7281 7282 #undef __FUNCT__ 7283 #define __FUNCT__ "DMPlexGetDepth" 7284 /*@ 7285 DMPlexGetDepth - get the number of strata 7286 7287 Not Collective 7288 7289 Input Parameters: 7290 . dm - The DMPlex object 7291 7292 Output Parameters: 7293 . depth - number of strata 7294 7295 Level: developer 7296 7297 Notes: 7298 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7299 7300 .keywords: mesh, points 7301 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7302 @*/ 7303 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7304 { 7305 PetscInt d; 7306 PetscErrorCode ierr; 7307 7308 PetscFunctionBegin; 7309 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7310 PetscValidPointer(depth, 2); 7311 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7312 *depth = d-1; 7313 PetscFunctionReturn(0); 7314 } 7315 7316 #undef __FUNCT__ 7317 #define __FUNCT__ "DMPlexGetDepthStratum" 7318 /*@ 7319 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7320 7321 Not Collective 7322 7323 Input Parameters: 7324 + dm - The DMPlex object 7325 - stratumValue - The requested depth 7326 7327 Output Parameters: 7328 + start - The first point at this depth 7329 - end - One beyond the last point at this depth 7330 7331 Level: developer 7332 7333 .keywords: mesh, points 7334 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7335 @*/ 7336 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7337 { 7338 DM_Plex *mesh = (DM_Plex *) dm->data; 7339 DMLabel next = mesh->labels; 7340 PetscBool flg = PETSC_FALSE; 7341 PetscInt depth; 7342 PetscErrorCode ierr; 7343 7344 PetscFunctionBegin; 7345 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7346 if (stratumValue < 0) { 7347 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7348 PetscFunctionReturn(0); 7349 } else { 7350 PetscInt pStart, pEnd; 7351 7352 if (start) {*start = 0;} 7353 if (end) {*end = 0;} 7354 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7355 if (pStart == pEnd) {PetscFunctionReturn(0);} 7356 } 7357 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7358 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7359 /* We should have a generic GetLabel() and a Label class */ 7360 while(next) { 7361 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7362 if (flg) break; 7363 next = next->next; 7364 } 7365 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7366 depth = stratumValue; 7367 if ((depth < 0) || (depth >= next->numStrata)) { 7368 if (start) {*start = 0;} 7369 if (end) {*end = 0;} 7370 } else { 7371 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7372 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7373 } 7374 PetscFunctionReturn(0); 7375 } 7376 7377 #undef __FUNCT__ 7378 #define __FUNCT__ "DMPlexGetHeightStratum" 7379 /*@ 7380 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7381 7382 Not Collective 7383 7384 Input Parameters: 7385 + dm - The DMPlex object 7386 - stratumValue - The requested height 7387 7388 Output Parameters: 7389 + start - The first point at this height 7390 - end - One beyond the last point at this height 7391 7392 Level: developer 7393 7394 .keywords: mesh, points 7395 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7396 @*/ 7397 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7398 { 7399 DM_Plex *mesh = (DM_Plex *) dm->data; 7400 DMLabel next = mesh->labels; 7401 PetscBool flg = PETSC_FALSE; 7402 PetscInt depth; 7403 PetscErrorCode ierr; 7404 7405 PetscFunctionBegin; 7406 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7407 if (stratumValue < 0) { 7408 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7409 } else { 7410 PetscInt pStart, pEnd; 7411 7412 if (start) {*start = 0;} 7413 if (end) {*end = 0;} 7414 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7415 if (pStart == pEnd) {PetscFunctionReturn(0);} 7416 } 7417 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7418 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7419 /* We should have a generic GetLabel() and a Label class */ 7420 while(next) { 7421 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7422 if (flg) break; 7423 next = next->next; 7424 } 7425 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7426 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7427 if ((depth < 0) || (depth >= next->numStrata)) { 7428 if (start) {*start = 0;} 7429 if (end) {*end = 0;} 7430 } else { 7431 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7432 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7433 } 7434 PetscFunctionReturn(0); 7435 } 7436 7437 #undef __FUNCT__ 7438 #define __FUNCT__ "DMPlexCreateSectionInitial" 7439 /* Set the number of dof on each point and separate by fields */ 7440 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) { 7441 PetscInt *numDofTot; 7442 PetscInt pStart = 0, pEnd = 0; 7443 PetscInt p, d, f; 7444 PetscErrorCode ierr; 7445 7446 PetscFunctionBegin; 7447 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7448 for(d = 0; d <= dim; ++d) { 7449 numDofTot[d] = 0; 7450 for(f = 0; f < numFields; ++f) { 7451 numDofTot[d] += numDof[f*(dim+1)+d]; 7452 } 7453 } 7454 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7455 if (numFields > 0) { 7456 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7457 if (numComp) { 7458 for(f = 0; f < numFields; ++f) { 7459 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7460 } 7461 } 7462 } 7463 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7464 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7465 for(d = 0; d <= dim; ++d) { 7466 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7467 for(p = pStart; p < pEnd; ++p) { 7468 for(f = 0; f < numFields; ++f) { 7469 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7470 } 7471 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7472 } 7473 } 7474 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7475 PetscFunctionReturn(0); 7476 } 7477 7478 #undef __FUNCT__ 7479 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7480 /* Set the number of dof on each point and separate by fields 7481 If constDof is PETSC_DETERMINE, constrain every dof on the point 7482 */ 7483 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) { 7484 PetscInt numFields; 7485 PetscInt bc; 7486 PetscErrorCode ierr; 7487 7488 PetscFunctionBegin; 7489 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7490 for (bc = 0; bc < numBC; ++bc) { 7491 PetscInt field = 0; 7492 const PetscInt *idx; 7493 PetscInt n, i; 7494 7495 if (numFields) {field = bcField[bc];} 7496 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7497 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7498 for (i = 0; i < n; ++i) { 7499 const PetscInt p = idx[i]; 7500 PetscInt numConst = constDof; 7501 7502 /* Constrain every dof on the point */ 7503 if (numConst < 0) { 7504 if (numFields) { 7505 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7506 } else { 7507 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7508 } 7509 } 7510 if (numFields) { 7511 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7512 } 7513 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7514 } 7515 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7516 } 7517 PetscFunctionReturn(0); 7518 } 7519 7520 #undef __FUNCT__ 7521 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7522 /* Set the constrained indices on each point and separate by fields */ 7523 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7524 { 7525 PetscInt *maxConstraints; 7526 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7527 PetscErrorCode ierr; 7528 7529 PetscFunctionBegin; 7530 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7531 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7532 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7533 for(f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 7534 for(p = pStart; p < pEnd; ++p) { 7535 PetscInt cdof; 7536 7537 if (numFields) { 7538 for(f = 0; f < numFields; ++f) { 7539 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7540 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7541 } 7542 } else { 7543 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7544 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7545 } 7546 } 7547 for (f = 0; f < numFields; ++f) { 7548 maxConstraints[numFields] += maxConstraints[f]; 7549 } 7550 if (maxConstraints[numFields]) { 7551 PetscInt *indices; 7552 7553 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7554 for (p = pStart; p < pEnd; ++p) { 7555 PetscInt cdof, d; 7556 7557 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7558 if (cdof) { 7559 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7560 if (numFields) { 7561 PetscInt numConst = 0, foff = 0; 7562 7563 for (f = 0; f < numFields; ++f) { 7564 PetscInt cfdof, fdof; 7565 7566 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7567 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7568 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7569 for(d = 0; d < cfdof; ++d) { 7570 indices[numConst+d] = d; 7571 } 7572 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7573 for(d = 0; d < cfdof; ++d) { 7574 indices[numConst+d] += foff; 7575 } 7576 numConst += cfdof; 7577 foff += fdof; 7578 } 7579 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7580 } else { 7581 for (d = 0; d < cdof; ++d) { 7582 indices[d] = d; 7583 } 7584 } 7585 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7586 } 7587 } 7588 ierr = PetscFree(indices);CHKERRQ(ierr); 7589 } 7590 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7591 PetscFunctionReturn(0); 7592 } 7593 7594 #undef __FUNCT__ 7595 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7596 /* Set the constrained field indices on each point */ 7597 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7598 { 7599 const PetscInt *points, *indices; 7600 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7601 PetscErrorCode ierr; 7602 7603 PetscFunctionBegin; 7604 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7605 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7606 7607 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7608 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7609 if (!constraintIndices) { 7610 PetscInt *idx, i; 7611 7612 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7613 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7614 for(i = 0; i < maxDof; ++i) {idx[i] = i;} 7615 for(p = 0; p < numPoints; ++p) { 7616 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7617 } 7618 ierr = PetscFree(idx);CHKERRQ(ierr); 7619 } else { 7620 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7621 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7622 for(p = 0; p < numPoints; ++p) { 7623 PetscInt fcdof; 7624 7625 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7626 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); 7627 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7628 } 7629 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7630 } 7631 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7632 PetscFunctionReturn(0); 7633 } 7634 7635 #undef __FUNCT__ 7636 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7637 /* Set the constrained indices on each point and separate by fields */ 7638 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7639 { 7640 PetscInt *indices; 7641 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7642 PetscErrorCode ierr; 7643 7644 PetscFunctionBegin; 7645 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7646 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7647 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7648 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7649 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7650 for (p = pStart; p < pEnd; ++p) { 7651 PetscInt cdof, d; 7652 7653 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7654 if (cdof) { 7655 PetscInt numConst = 0, foff = 0; 7656 7657 for (f = 0; f < numFields; ++f) { 7658 const PetscInt *fcind; 7659 PetscInt fdof, fcdof; 7660 7661 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7662 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7663 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7664 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7665 for(d = 0; d < fcdof; ++d) { 7666 indices[numConst+d] = fcind[d]+foff; 7667 } 7668 foff += fdof; 7669 numConst += fcdof; 7670 } 7671 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7672 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7673 } 7674 } 7675 ierr = PetscFree(indices);CHKERRQ(ierr); 7676 PetscFunctionReturn(0); 7677 } 7678 7679 #undef __FUNCT__ 7680 #define __FUNCT__ "DMPlexCreateSection" 7681 /*@C 7682 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7683 7684 Not Collective 7685 7686 Input Parameters: 7687 + dm - The DMPlex object 7688 . dim - The spatial dimension of the problem 7689 . numFields - The number of fields in the problem 7690 . numComp - An array of size numFields that holds the number of components for each field 7691 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7692 . numBC - The number of boundary conditions 7693 . bcField - An array of size numBC giving the field number for each boundry condition 7694 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7695 7696 Output Parameter: 7697 . section - The PetscSection object 7698 7699 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 7700 nubmer of dof for field 0 on each edge. 7701 7702 Level: developer 7703 7704 .keywords: mesh, elements 7705 .seealso: DMPlexCreate(), PetscSectionCreate() 7706 @*/ 7707 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) { 7708 PetscErrorCode ierr; 7709 7710 PetscFunctionBegin; 7711 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7712 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7713 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7714 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7715 { 7716 PetscBool view = PETSC_FALSE; 7717 7718 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7719 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7720 } 7721 PetscFunctionReturn(0); 7722 } 7723 7724 #undef __FUNCT__ 7725 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7726 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 7727 { 7728 PetscSection section; 7729 PetscErrorCode ierr; 7730 7731 PetscFunctionBegin; 7732 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7733 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 7734 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7735 PetscFunctionReturn(0); 7736 } 7737 7738 #undef __FUNCT__ 7739 #define __FUNCT__ "DMPlexGetCoordinateSection" 7740 /*@ 7741 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7742 7743 Not Collective 7744 7745 Input Parameter: 7746 . dm - The DMPlex object 7747 7748 Output Parameter: 7749 . section - The PetscSection object 7750 7751 Level: intermediate 7752 7753 .keywords: mesh, coordinates 7754 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7755 @*/ 7756 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 7757 { 7758 DM cdm; 7759 PetscErrorCode ierr; 7760 7761 PetscFunctionBegin; 7762 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7763 PetscValidPointer(section, 2); 7764 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7765 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7766 PetscFunctionReturn(0); 7767 } 7768 7769 #undef __FUNCT__ 7770 #define __FUNCT__ "DMPlexSetCoordinateSection" 7771 /*@ 7772 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7773 7774 Not Collective 7775 7776 Input Parameters: 7777 + dm - The DMPlex object 7778 - section - The PetscSection object 7779 7780 Level: intermediate 7781 7782 .keywords: mesh, coordinates 7783 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7784 @*/ 7785 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 7786 { 7787 DM cdm; 7788 PetscErrorCode ierr; 7789 7790 PetscFunctionBegin; 7791 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7792 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7793 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7794 PetscFunctionReturn(0); 7795 } 7796 7797 #undef __FUNCT__ 7798 #define __FUNCT__ "DMPlexGetConeSection" 7799 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 7800 { 7801 DM_Plex *mesh = (DM_Plex *) dm->data; 7802 7803 PetscFunctionBegin; 7804 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7805 if (section) *section = mesh->coneSection; 7806 PetscFunctionReturn(0); 7807 } 7808 7809 #undef __FUNCT__ 7810 #define __FUNCT__ "DMPlexGetCones" 7811 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) { 7812 DM_Plex *mesh = (DM_Plex *) dm->data; 7813 7814 PetscFunctionBegin; 7815 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7816 if (cones) *cones = mesh->cones; 7817 PetscFunctionReturn(0); 7818 } 7819 7820 #undef __FUNCT__ 7821 #define __FUNCT__ "DMPlexGetConeOrientations" 7822 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) { 7823 DM_Plex *mesh = (DM_Plex *) dm->data; 7824 7825 PetscFunctionBegin; 7826 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7827 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7828 PetscFunctionReturn(0); 7829 } 7830 7831 #undef __FUNCT__ 7832 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7833 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7834 { 7835 const PetscInt embedDim = 2; 7836 PetscReal x = PetscRealPart(point[0]); 7837 PetscReal y = PetscRealPart(point[1]); 7838 PetscReal v0[2], J[4], invJ[4], detJ; 7839 PetscReal xi, eta; 7840 PetscErrorCode ierr; 7841 7842 PetscFunctionBegin; 7843 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7844 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7845 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7846 7847 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 7848 *cell = c; 7849 } else { 7850 *cell = -1; 7851 } 7852 PetscFunctionReturn(0); 7853 } 7854 7855 #undef __FUNCT__ 7856 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7857 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7858 { 7859 PetscSection coordSection; 7860 Vec coordsLocal; 7861 const PetscScalar *coords; 7862 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7863 PetscReal x = PetscRealPart(point[0]); 7864 PetscReal y = PetscRealPart(point[1]); 7865 PetscInt crossings = 0, f; 7866 PetscErrorCode ierr; 7867 7868 PetscFunctionBegin; 7869 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7870 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7871 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7872 for(f = 0; f < 4; ++f) { 7873 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7874 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7875 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7876 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7877 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7878 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7879 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7880 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7881 if ((cond1 || cond2) && above) ++crossings; 7882 } 7883 if (crossings % 2) { 7884 *cell = c; 7885 } else { 7886 *cell = -1; 7887 } 7888 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7889 PetscFunctionReturn(0); 7890 } 7891 7892 #undef __FUNCT__ 7893 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7894 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7895 { 7896 const PetscInt embedDim = 3; 7897 PetscReal v0[3], J[9], invJ[9], detJ; 7898 PetscReal x = PetscRealPart(point[0]); 7899 PetscReal y = PetscRealPart(point[1]); 7900 PetscReal z = PetscRealPart(point[2]); 7901 PetscReal xi, eta, zeta; 7902 PetscErrorCode ierr; 7903 7904 PetscFunctionBegin; 7905 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7906 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7907 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7908 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7909 7910 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 7911 *cell = c; 7912 } else { 7913 *cell = -1; 7914 } 7915 PetscFunctionReturn(0); 7916 } 7917 7918 #undef __FUNCT__ 7919 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7920 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7921 { 7922 PetscSection coordSection; 7923 Vec coordsLocal; 7924 const PetscScalar *coords; 7925 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7926 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7927 PetscBool found = PETSC_TRUE; 7928 PetscInt f; 7929 PetscErrorCode ierr; 7930 7931 PetscFunctionBegin; 7932 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7933 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7934 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7935 for(f = 0; f < 6; ++f) { 7936 /* Check the point is under plane */ 7937 /* Get face normal */ 7938 PetscReal v_i[3] = {PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]), 7939 PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]), 7940 PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2])}; 7941 PetscReal v_j[3] = {PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]), 7942 PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]), 7943 PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2])}; 7944 PetscReal normal[3] = {v_i[1]*v_j[2] - v_i[2]*v_j[1], v_i[2]*v_j[0] - v_i[0]*v_j[2], v_i[0]*v_j[1] - v_i[1]*v_j[0]}; 7945 PetscReal pp[3] = {PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]), 7946 PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]), 7947 PetscRealPart(coords[faces[f*4+0]*3+2] - point[2])}; 7948 PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7949 /* Check that projected point is in face (2D location problem) */ 7950 if (dot < 0.0) { 7951 found = PETSC_FALSE; 7952 break; 7953 } 7954 } 7955 if (found) { 7956 *cell = c; 7957 } else { 7958 *cell = -1; 7959 } 7960 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7961 PetscFunctionReturn(0); 7962 } 7963 7964 #undef __FUNCT__ 7965 #define __FUNCT__ "DMLocatePoints_Plex" 7966 /* 7967 Need to implement using the guess 7968 */ 7969 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7970 { 7971 PetscInt cell = -1/*, guess = -1*/; 7972 PetscInt bs, numPoints, p; 7973 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7974 PetscInt *cells; 7975 PetscScalar *a; 7976 PetscErrorCode ierr; 7977 7978 PetscFunctionBegin; 7979 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7980 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7981 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7982 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 7983 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7984 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7985 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7986 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); 7987 numPoints /= bs; 7988 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7989 for(p = 0; p < numPoints; ++p) { 7990 const PetscScalar *point = &a[p*bs]; 7991 7992 switch(dim) { 7993 case 2: 7994 for(c = cStart; c < cEnd; ++c) { 7995 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7996 switch(coneSize) { 7997 case 3: 7998 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7999 break; 8000 case 4: 8001 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8002 break; 8003 default: 8004 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8005 } 8006 if (cell >= 0) break; 8007 } 8008 break; 8009 case 3: 8010 for(c = cStart; c < cEnd; ++c) { 8011 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8012 switch(coneSize) { 8013 case 4: 8014 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8015 break; 8016 case 8: 8017 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8018 break; 8019 default: 8020 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8021 } 8022 if (cell >= 0) break; 8023 } 8024 break; 8025 default: 8026 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8027 } 8028 cells[p] = cell; 8029 } 8030 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8031 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8032 PetscFunctionReturn(0); 8033 } 8034 8035 /******************************** FEM Support **********************************/ 8036 8037 #undef __FUNCT__ 8038 #define __FUNCT__ "DMPlexVecGetClosure" 8039 /*@C 8040 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8041 8042 Not collective 8043 8044 Input Parameters: 8045 + dm - The DM 8046 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8047 . v - The local vector 8048 - point - The sieve point in the DM 8049 8050 Output Parameters: 8051 + csize - The number of values in the closure, or PETSC_NULL 8052 - values - The array of values, which is a borrowed array and should not be freed 8053 8054 Level: intermediate 8055 8056 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8057 @*/ 8058 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 8059 PetscScalar *array, *vArray; 8060 PetscInt *points = PETSC_NULL; 8061 PetscInt offsets[32]; 8062 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8063 PetscErrorCode ierr; 8064 8065 PetscFunctionBegin; 8066 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8067 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8068 if (!section) { 8069 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8070 } 8071 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8072 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8073 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8074 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8075 /* Compress out points not in the section */ 8076 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8077 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8078 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8079 points[q*2] = points[p]; 8080 points[q*2+1] = points[p+1]; 8081 ++q; 8082 } 8083 } 8084 numPoints = q; 8085 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8086 PetscInt dof, fdof; 8087 8088 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8089 for (f = 0; f < numFields; ++f) { 8090 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8091 offsets[f+1] += fdof; 8092 } 8093 size += dof; 8094 } 8095 for (f = 1; f < numFields; ++f) { 8096 offsets[f+1] += offsets[f]; 8097 } 8098 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8099 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8100 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8101 for (p = 0; p < numPoints*2; p += 2) { 8102 PetscInt o = points[p+1]; 8103 PetscInt dof, off, d; 8104 PetscScalar *varr; 8105 8106 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8107 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8108 varr = &vArray[off]; 8109 if (numFields) { 8110 PetscInt fdof, foff, fcomp, f, c; 8111 8112 for (f = 0, foff = 0; f < numFields; ++f) { 8113 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8114 if (o >= 0) { 8115 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8116 array[offsets[f]] = varr[foff+d]; 8117 } 8118 } else { 8119 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8120 for (d = fdof/fcomp-1; d >= 0; --d) { 8121 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8122 array[offsets[f]] = varr[foff+d*fcomp+c]; 8123 } 8124 } 8125 } 8126 foff += fdof; 8127 } 8128 } else { 8129 if (o >= 0) { 8130 for (d = 0; d < dof; ++d, ++offsets[0]) { 8131 array[offsets[0]] = varr[d]; 8132 } 8133 } else { 8134 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8135 array[offsets[0]] = varr[d]; 8136 } 8137 } 8138 } 8139 } 8140 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8141 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8142 if (csize) *csize = size; 8143 *values = array; 8144 PetscFunctionReturn(0); 8145 } 8146 8147 #undef __FUNCT__ 8148 #define __FUNCT__ "DMPlexVecRestoreClosure" 8149 /*@C 8150 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8151 8152 Not collective 8153 8154 Input Parameters: 8155 + dm - The DM 8156 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8157 . v - The local vector 8158 . point - The sieve point in the DM 8159 . csize - The number of values in the closure, or PETSC_NULL 8160 - values - The array of values, which is a borrowed array and should not be freed 8161 8162 Level: intermediate 8163 8164 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8165 @*/ 8166 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 8167 PetscInt size = 0; 8168 PetscErrorCode ierr; 8169 8170 PetscFunctionBegin; 8171 /* Should work without recalculating size */ 8172 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 8173 PetscFunctionReturn(0); 8174 } 8175 8176 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8177 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8178 8179 #undef __FUNCT__ 8180 #define __FUNCT__ "updatePoint_private" 8181 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8182 { 8183 PetscInt cdof; /* The number of constraints on this point */ 8184 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8185 PetscScalar *a; 8186 PetscInt off, cind = 0, k; 8187 PetscErrorCode ierr; 8188 8189 PetscFunctionBegin; 8190 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8191 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8192 a = &array[off]; 8193 if (!cdof || setBC) { 8194 if (orientation >= 0) { 8195 for (k = 0; k < dof; ++k) { 8196 fuse(&a[k], values[k]); 8197 } 8198 } else { 8199 for (k = 0; k < dof; ++k) { 8200 fuse(&a[k], values[dof-k-1]); 8201 } 8202 } 8203 } else { 8204 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8205 if (orientation >= 0) { 8206 for (k = 0; k < dof; ++k) { 8207 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8208 fuse(&a[k], values[k]); 8209 } 8210 } else { 8211 for (k = 0; k < dof; ++k) { 8212 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8213 fuse(&a[k], values[dof-k-1]); 8214 } 8215 } 8216 } 8217 PetscFunctionReturn(0); 8218 } 8219 8220 #undef __FUNCT__ 8221 #define __FUNCT__ "updatePointFields_private" 8222 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) { 8223 PetscScalar *a; 8224 PetscInt numFields, off, foff, f; 8225 PetscErrorCode ierr; 8226 8227 PetscFunctionBegin; 8228 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8229 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8230 a = &array[off]; 8231 for (f = 0, foff = 0; f < numFields; ++f) { 8232 PetscInt fdof, fcomp, fcdof; 8233 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8234 PetscInt cind = 0, k, c; 8235 8236 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8237 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8238 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8239 if (!fcdof || setBC) { 8240 if (orientation >= 0) { 8241 for (k = 0; k < fdof; ++k) { 8242 fuse(&a[foff+k], values[foffs[f]+k]); 8243 } 8244 } else { 8245 for (k = fdof/fcomp-1; k >= 0; --k) { 8246 for (c = 0; c < fcomp; ++c) { 8247 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8248 } 8249 } 8250 } 8251 } else { 8252 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8253 if (orientation >= 0) { 8254 for (k = 0; k < fdof; ++k) { 8255 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8256 fuse(&a[foff+k], values[foffs[f]+k]); 8257 } 8258 } else { 8259 for (k = fdof/fcomp-1; k >= 0; --k) { 8260 for (c = 0; c < fcomp; ++c) { 8261 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8262 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8263 } 8264 } 8265 } 8266 } 8267 foff += fdof; 8268 foffs[f] += fdof; 8269 } 8270 PetscFunctionReturn(0); 8271 } 8272 8273 #undef __FUNCT__ 8274 #define __FUNCT__ "DMPlexVecSetClosure" 8275 /*@C 8276 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8277 8278 Not collective 8279 8280 Input Parameters: 8281 + dm - The DM 8282 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8283 . v - The local vector 8284 . point - The sieve point in the DM 8285 . values - The array of values, which is a borrowed array and should not be freed 8286 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8287 8288 Level: intermediate 8289 8290 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8291 @*/ 8292 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) { 8293 PetscScalar *array; 8294 PetscInt *points = PETSC_NULL; 8295 PetscInt offsets[32]; 8296 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8297 PetscErrorCode ierr; 8298 8299 PetscFunctionBegin; 8300 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8301 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8302 if (!section) { 8303 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8304 } 8305 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8306 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8307 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8308 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8309 /* Compress out points not in the section */ 8310 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8311 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8312 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8313 points[q*2] = points[p]; 8314 points[q*2+1] = points[p+1]; 8315 ++q; 8316 } 8317 } 8318 numPoints = q; 8319 for (p = 0; p < numPoints*2; p += 2) { 8320 PetscInt fdof; 8321 8322 for (f = 0; f < numFields; ++f) { 8323 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8324 offsets[f+1] += fdof; 8325 } 8326 } 8327 for (f = 1; f < numFields; ++f) { 8328 offsets[f+1] += offsets[f]; 8329 } 8330 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8331 if (numFields) { 8332 switch(mode) { 8333 case INSERT_VALUES: 8334 for (p = 0; p < numPoints*2; p += 2) { 8335 PetscInt o = points[p+1]; 8336 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8337 } break; 8338 case INSERT_ALL_VALUES: 8339 for (p = 0; p < numPoints*2; p += 2) { 8340 PetscInt o = points[p+1]; 8341 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8342 } break; 8343 case ADD_VALUES: 8344 for (p = 0; p < numPoints*2; p += 2) { 8345 PetscInt o = points[p+1]; 8346 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8347 } break; 8348 case ADD_ALL_VALUES: 8349 for (p = 0; p < numPoints*2; p += 2) { 8350 PetscInt o = points[p+1]; 8351 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8352 } break; 8353 default: 8354 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8355 } 8356 } else { 8357 switch(mode) { 8358 case INSERT_VALUES: 8359 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8360 PetscInt o = points[p+1]; 8361 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8362 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8363 } break; 8364 case INSERT_ALL_VALUES: 8365 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8366 PetscInt o = points[p+1]; 8367 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8368 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8369 } break; 8370 case ADD_VALUES: 8371 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8372 PetscInt o = points[p+1]; 8373 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8374 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8375 } break; 8376 case ADD_ALL_VALUES: 8377 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8378 PetscInt o = points[p+1]; 8379 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8380 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8381 } break; 8382 default: 8383 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8384 } 8385 } 8386 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8387 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8388 PetscFunctionReturn(0); 8389 } 8390 8391 #undef __FUNCT__ 8392 #define __FUNCT__ "DMPlexPrintMatSetValues" 8393 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8394 { 8395 PetscMPIInt rank; 8396 PetscInt i, j; 8397 PetscErrorCode ierr; 8398 8399 PetscFunctionBegin; 8400 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8401 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8402 for (i = 0; i < numIndices; i++) { 8403 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8404 } 8405 for (i = 0; i < numIndices; i++) { 8406 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8407 for (j = 0; j < numIndices; j++) { 8408 #ifdef PETSC_USE_COMPLEX 8409 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8410 #else 8411 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8412 #endif 8413 } 8414 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8415 } 8416 PetscFunctionReturn(0); 8417 } 8418 8419 #undef __FUNCT__ 8420 #define __FUNCT__ "indicesPoint_private" 8421 /* . off - The global offset of this point */ 8422 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 8423 PetscInt cdof; /* The number of constraints on this point */ 8424 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8425 PetscInt cind = 0, k; 8426 PetscErrorCode ierr; 8427 8428 PetscFunctionBegin; 8429 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8430 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8431 if (!cdof || setBC) { 8432 if (orientation >= 0) { 8433 for (k = 0; k < dof; ++k) { 8434 indices[k] = off+k; 8435 } 8436 } else { 8437 for (k = 0; k < dof; ++k) { 8438 indices[dof-k-1] = off+k; 8439 } 8440 } 8441 } else { 8442 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8443 if (orientation >= 0) { 8444 for (k = 0; k < dof; ++k) { 8445 if ((cind < cdof) && (k == cdofs[cind])) { 8446 /* Insert check for returning constrained indices */ 8447 indices[k] = -(off+k+1); 8448 ++cind; 8449 } else { 8450 indices[k] = off+k-cind; 8451 } 8452 } 8453 } else { 8454 for (k = 0; k < dof; ++k) { 8455 if ((cind < cdof) && (k == cdofs[cind])) { 8456 /* Insert check for returning constrained indices */ 8457 indices[dof-k-1] = -(off+k+1); 8458 ++cind; 8459 } else { 8460 indices[dof-k-1] = off+k-cind; 8461 } 8462 } 8463 } 8464 } 8465 PetscFunctionReturn(0); 8466 } 8467 8468 #undef __FUNCT__ 8469 #define __FUNCT__ "indicesPointFields_private" 8470 /* . off - The global offset of this point */ 8471 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 8472 PetscInt numFields, foff, f; 8473 PetscErrorCode ierr; 8474 8475 PetscFunctionBegin; 8476 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8477 for (f = 0, foff = 0; f < numFields; ++f) { 8478 PetscInt fdof, fcomp, cfdof; 8479 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8480 PetscInt cind = 0, k, c; 8481 8482 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8483 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8484 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8485 if (!cfdof || setBC) { 8486 if (orientation >= 0) { 8487 for (k = 0; k < fdof; ++k) { 8488 indices[foffs[f]+k] = off+foff+k; 8489 } 8490 } else { 8491 for (k = fdof/fcomp-1; k >= 0; --k) { 8492 for (c = 0; c < fcomp; ++c) { 8493 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8494 } 8495 } 8496 } 8497 } else { 8498 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8499 if (orientation >= 0) { 8500 for (k = 0; k < fdof; ++k) { 8501 if ((cind < cfdof) && (k == fcdofs[cind])) { 8502 indices[foffs[f]+k] = -(off+foff+k+1); 8503 ++cind; 8504 } else { 8505 indices[foffs[f]+k] = off+foff+k-cind; 8506 } 8507 } 8508 } else { 8509 for (k = fdof/fcomp-1; k >= 0; --k) { 8510 for (c = 0; c < fcomp; ++c) { 8511 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8512 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8513 ++cind; 8514 } else { 8515 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8516 } 8517 } 8518 } 8519 } 8520 } 8521 foff += fdof - cfdof; 8522 foffs[f] += fdof; 8523 } 8524 PetscFunctionReturn(0); 8525 } 8526 8527 #undef __FUNCT__ 8528 #define __FUNCT__ "DMPlexMatSetClosure" 8529 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8530 { 8531 DM_Plex *mesh = (DM_Plex *) dm->data; 8532 PetscInt *points = PETSC_NULL; 8533 PetscInt *indices; 8534 PetscInt offsets[32]; 8535 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8536 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8537 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8538 PetscErrorCode ierr; 8539 8540 PetscFunctionBegin; 8541 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8542 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8543 if (useDefault) { 8544 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8545 } 8546 if (useGlobalDefault) { 8547 if (useDefault) { 8548 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8549 } else { 8550 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8551 } 8552 } 8553 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8554 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8555 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8556 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8557 /* Compress out points not in the section */ 8558 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8559 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8560 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8561 points[q*2] = points[p]; 8562 points[q*2+1] = points[p+1]; 8563 ++q; 8564 } 8565 } 8566 numPoints = q; 8567 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8568 PetscInt fdof; 8569 8570 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8571 for (f = 0; f < numFields; ++f) { 8572 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8573 offsets[f+1] += fdof; 8574 } 8575 numIndices += dof; 8576 } 8577 for (f = 1; f < numFields; ++f) { 8578 offsets[f+1] += offsets[f]; 8579 } 8580 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8581 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8582 if (numFields) { 8583 for (p = 0; p < numPoints*2; p += 2) { 8584 PetscInt o = points[p+1]; 8585 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8586 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8587 } 8588 } else { 8589 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8590 PetscInt o = points[p+1]; 8591 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8592 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8593 } 8594 } 8595 if (useGlobalDefault && !useDefault) { 8596 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8597 } 8598 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8599 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8600 if (ierr) { 8601 PetscMPIInt rank; 8602 PetscErrorCode ierr2; 8603 8604 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8605 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8606 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8607 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8608 CHKERRQ(ierr); 8609 } 8610 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8611 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8612 PetscFunctionReturn(0); 8613 } 8614 8615 #undef __FUNCT__ 8616 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8617 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8618 { 8619 PetscSection coordSection; 8620 Vec coordinates; 8621 const PetscScalar *coords; 8622 const PetscInt dim = 2; 8623 PetscInt d, f; 8624 PetscErrorCode ierr; 8625 8626 PetscFunctionBegin; 8627 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8628 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8629 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8630 if (v0) { 8631 for (d = 0; d < dim; d++) { 8632 v0[d] = PetscRealPart(coords[d]); 8633 } 8634 } 8635 if (J) { 8636 for (d = 0; d < dim; d++) { 8637 for (f = 0; f < dim; f++) { 8638 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8639 } 8640 } 8641 *detJ = J[0]*J[3] - J[1]*J[2]; 8642 #if 0 8643 if (detJ < 0.0) { 8644 const PetscReal xLength = mesh->periodicity[0]; 8645 8646 if (xLength != 0.0) { 8647 PetscReal v0x = coords[0*dim+0]; 8648 8649 if (v0x == 0.0) { 8650 v0x = v0[0] = xLength; 8651 } 8652 for (f = 0; f < dim; f++) { 8653 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8654 8655 J[0*dim+f] = 0.5*(px - v0x); 8656 } 8657 } 8658 detJ = J[0]*J[3] - J[1]*J[2]; 8659 } 8660 #endif 8661 PetscLogFlops(8.0 + 3.0); 8662 } 8663 if (invJ) { 8664 const PetscReal invDet = 1.0/(*detJ); 8665 8666 invJ[0] = invDet*J[3]; 8667 invJ[1] = -invDet*J[1]; 8668 invJ[2] = -invDet*J[2]; 8669 invJ[3] = invDet*J[0]; 8670 PetscLogFlops(5.0); 8671 } 8672 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8673 PetscFunctionReturn(0); 8674 } 8675 8676 #undef __FUNCT__ 8677 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8678 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8679 { 8680 PetscSection coordSection; 8681 Vec coordinates; 8682 const PetscScalar *coords; 8683 const PetscInt dim = 2; 8684 PetscInt d, f; 8685 PetscErrorCode ierr; 8686 8687 PetscFunctionBegin; 8688 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8689 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8690 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8691 if (v0) { 8692 for (d = 0; d < dim; d++) { 8693 v0[d] = PetscRealPart(coords[d]); 8694 } 8695 } 8696 if (J) { 8697 for (d = 0; d < dim; d++) { 8698 for (f = 0; f < dim; f++) { 8699 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8700 } 8701 } 8702 *detJ = J[0]*J[3] - J[1]*J[2]; 8703 PetscLogFlops(8.0 + 3.0); 8704 } 8705 if (invJ) { 8706 const PetscReal invDet = 1.0/(*detJ); 8707 8708 invJ[0] = invDet*J[3]; 8709 invJ[1] = -invDet*J[1]; 8710 invJ[2] = -invDet*J[2]; 8711 invJ[3] = invDet*J[0]; 8712 PetscLogFlops(5.0); 8713 } 8714 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8715 PetscFunctionReturn(0); 8716 } 8717 8718 #undef __FUNCT__ 8719 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8720 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8721 { 8722 PetscSection coordSection; 8723 Vec coordinates; 8724 const PetscScalar *coords; 8725 const PetscInt dim = 3; 8726 PetscInt d, f; 8727 PetscErrorCode ierr; 8728 8729 PetscFunctionBegin; 8730 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8731 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8732 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8733 if (v0) { 8734 for (d = 0; d < dim; d++) { 8735 v0[d] = PetscRealPart(coords[d]); 8736 } 8737 } 8738 if (J) { 8739 for (d = 0; d < dim; d++) { 8740 for (f = 0; f < dim; f++) { 8741 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8742 } 8743 } 8744 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8745 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8746 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8747 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8748 PetscLogFlops(18.0 + 12.0); 8749 } 8750 if (invJ) { 8751 const PetscReal invDet = 1.0/(*detJ); 8752 8753 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8754 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8755 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8756 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8757 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8758 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8759 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8760 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8761 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8762 PetscLogFlops(37.0); 8763 } 8764 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8765 PetscFunctionReturn(0); 8766 } 8767 8768 #undef __FUNCT__ 8769 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8770 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8771 { 8772 PetscSection coordSection; 8773 Vec coordinates; 8774 const PetscScalar *coords; 8775 const PetscInt dim = 3; 8776 PetscInt d; 8777 PetscErrorCode ierr; 8778 8779 PetscFunctionBegin; 8780 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8781 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8782 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8783 if (v0) { 8784 for (d = 0; d < dim; d++) { 8785 v0[d] = PetscRealPart(coords[d]); 8786 } 8787 } 8788 if (J) { 8789 for (d = 0; d < dim; d++) { 8790 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8791 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8792 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8793 } 8794 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8795 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8796 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8797 PetscLogFlops(18.0 + 12.0); 8798 } 8799 if (invJ) { 8800 const PetscReal invDet = -1.0/(*detJ); 8801 8802 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8803 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8804 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8805 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8806 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8807 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8808 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8809 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8810 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8811 PetscLogFlops(37.0); 8812 } 8813 *detJ *= 8.0; 8814 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8815 PetscFunctionReturn(0); 8816 } 8817 8818 #undef __FUNCT__ 8819 #define __FUNCT__ "DMPlexComputeCellGeometry" 8820 /*@C 8821 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8822 8823 Collective on DM 8824 8825 Input Arguments: 8826 + dm - the DM 8827 - cell - the cell 8828 8829 Output Arguments: 8830 + v0 - the translation part of this affine transform 8831 . J - the Jacobian of the transform to the reference element 8832 . invJ - the inverse of the Jacobian 8833 - detJ - the Jacobian determinant 8834 8835 Level: advanced 8836 8837 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8838 @*/ 8839 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 8840 { 8841 PetscInt dim, coneSize; 8842 PetscErrorCode ierr; 8843 8844 PetscFunctionBegin; 8845 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8846 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8847 switch(dim) { 8848 case 2: 8849 switch(coneSize) { 8850 case 3: 8851 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8852 break; 8853 case 4: 8854 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8855 break; 8856 default: 8857 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8858 } 8859 break; 8860 case 3: 8861 switch(coneSize) { 8862 case 4: 8863 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8864 break; 8865 case 8: 8866 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8867 break; 8868 default: 8869 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8870 } 8871 break; 8872 default: 8873 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8874 } 8875 PetscFunctionReturn(0); 8876 } 8877 8878 #undef __FUNCT__ 8879 #define __FUNCT__ "DMPlexGetFaceOrientation" 8880 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) { 8881 MPI_Comm comm = ((PetscObject) dm)->comm; 8882 PetscBool posOrient = PETSC_FALSE; 8883 const PetscInt debug = 0; 8884 PetscInt cellDim, faceSize, f; 8885 PetscErrorCode ierr; 8886 8887 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 8888 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 8889 8890 if (cellDim == numCorners-1) { 8891 /* Simplices */ 8892 faceSize = numCorners-1; 8893 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 8894 } else if (cellDim == 1 && numCorners == 3) { 8895 /* Quadratic line */ 8896 faceSize = 1; 8897 posOrient = PETSC_TRUE; 8898 } else if (cellDim == 2 && numCorners == 4) { 8899 /* Quads */ 8900 faceSize = 2; 8901 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 8902 posOrient = PETSC_TRUE; 8903 } else if ((indices[0] == 3) && (indices[1] == 0)) { 8904 posOrient = PETSC_TRUE; 8905 } else { 8906 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 8907 posOrient = PETSC_FALSE; 8908 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 8909 } 8910 } else if (cellDim == 2 && numCorners == 6) { 8911 /* Quadratic triangle (I hate this) */ 8912 /* Edges are determined by the first 2 vertices (corners of edges) */ 8913 const PetscInt faceSizeTri = 3; 8914 PetscInt sortedIndices[3], i, iFace; 8915 PetscBool found = PETSC_FALSE; 8916 PetscInt faceVerticesTriSorted[9] = { 8917 0, 3, 4, /* bottom */ 8918 1, 4, 5, /* right */ 8919 2, 3, 5, /* left */ 8920 }; 8921 PetscInt faceVerticesTri[9] = { 8922 0, 3, 4, /* bottom */ 8923 1, 4, 5, /* right */ 8924 2, 5, 3, /* left */ 8925 }; 8926 8927 faceSize = faceSizeTri; 8928 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 8929 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 8930 for (iFace = 0; iFace < 3; ++iFace) { 8931 const PetscInt ii = iFace*faceSizeTri; 8932 PetscInt fVertex, cVertex; 8933 8934 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 8935 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 8936 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 8937 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 8938 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 8939 faceVertices[fVertex] = origVertices[cVertex]; 8940 break; 8941 } 8942 } 8943 } 8944 found = PETSC_TRUE; 8945 break; 8946 } 8947 } 8948 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 8949 if (posOriented) {*posOriented = PETSC_TRUE;} 8950 PetscFunctionReturn(0); 8951 } else if (cellDim == 2 && numCorners == 9) { 8952 /* Quadratic quad (I hate this) */ 8953 /* Edges are determined by the first 2 vertices (corners of edges) */ 8954 const PetscInt faceSizeQuad = 3; 8955 PetscInt sortedIndices[3], i, iFace; 8956 PetscBool found = PETSC_FALSE; 8957 PetscInt faceVerticesQuadSorted[12] = { 8958 0, 1, 4, /* bottom */ 8959 1, 2, 5, /* right */ 8960 2, 3, 6, /* top */ 8961 0, 3, 7, /* left */ 8962 }; 8963 PetscInt faceVerticesQuad[12] = { 8964 0, 1, 4, /* bottom */ 8965 1, 2, 5, /* right */ 8966 2, 3, 6, /* top */ 8967 3, 0, 7, /* left */ 8968 }; 8969 8970 faceSize = faceSizeQuad; 8971 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 8972 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 8973 for (iFace = 0; iFace < 4; ++iFace) { 8974 const PetscInt ii = iFace*faceSizeQuad; 8975 PetscInt fVertex, cVertex; 8976 8977 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 8978 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 8979 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 8980 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 8981 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 8982 faceVertices[fVertex] = origVertices[cVertex]; 8983 break; 8984 } 8985 } 8986 } 8987 found = PETSC_TRUE; 8988 break; 8989 } 8990 } 8991 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 8992 if (posOriented) {*posOriented = PETSC_TRUE;} 8993 PetscFunctionReturn(0); 8994 } else if (cellDim == 3 && numCorners == 8) { 8995 /* Hexes 8996 A hex is two oriented quads with the normal of the first 8997 pointing up at the second. 8998 8999 7---6 9000 /| /| 9001 4---5 | 9002 | 3-|-2 9003 |/ |/ 9004 0---1 9005 9006 Faces are determined by the first 4 vertices (corners of faces) */ 9007 const PetscInt faceSizeHex = 4; 9008 PetscInt sortedIndices[4], i, iFace; 9009 PetscBool found = PETSC_FALSE; 9010 PetscInt faceVerticesHexSorted[24] = { 9011 0, 1, 2, 3, /* bottom */ 9012 4, 5, 6, 7, /* top */ 9013 0, 1, 4, 5, /* front */ 9014 1, 2, 5, 6, /* right */ 9015 2, 3, 6, 7, /* back */ 9016 0, 3, 4, 7, /* left */ 9017 }; 9018 PetscInt faceVerticesHex[24] = { 9019 3, 2, 1, 0, /* bottom */ 9020 4, 5, 6, 7, /* top */ 9021 0, 1, 5, 4, /* front */ 9022 1, 2, 6, 5, /* right */ 9023 2, 3, 7, 6, /* back */ 9024 3, 0, 4, 7, /* left */ 9025 }; 9026 9027 faceSize = faceSizeHex; 9028 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9029 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9030 for (iFace = 0; iFace < 6; ++iFace) { 9031 const PetscInt ii = iFace*faceSizeHex; 9032 PetscInt fVertex, cVertex; 9033 9034 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9035 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9036 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9037 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9038 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9039 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9040 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9041 faceVertices[fVertex] = origVertices[cVertex]; 9042 break; 9043 } 9044 } 9045 } 9046 found = PETSC_TRUE; 9047 break; 9048 } 9049 } 9050 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9051 if (posOriented) {*posOriented = PETSC_TRUE;} 9052 PetscFunctionReturn(0); 9053 } else if (cellDim == 3 && numCorners == 10) { 9054 /* Quadratic tet */ 9055 /* Faces are determined by the first 3 vertices (corners of faces) */ 9056 const PetscInt faceSizeTet = 6; 9057 PetscInt sortedIndices[6], i, iFace; 9058 PetscBool found = PETSC_FALSE; 9059 PetscInt faceVerticesTetSorted[24] = { 9060 0, 1, 2, 6, 7, 8, /* bottom */ 9061 0, 3, 4, 6, 7, 9, /* front */ 9062 1, 4, 5, 7, 8, 9, /* right */ 9063 2, 3, 5, 6, 8, 9, /* left */ 9064 }; 9065 PetscInt faceVerticesTet[24] = { 9066 0, 1, 2, 6, 7, 8, /* bottom */ 9067 0, 4, 3, 6, 7, 9, /* front */ 9068 1, 5, 4, 7, 8, 9, /* right */ 9069 2, 3, 5, 8, 6, 9, /* left */ 9070 }; 9071 9072 faceSize = faceSizeTet; 9073 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9074 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9075 for (iFace=0; iFace < 4; ++iFace) { 9076 const PetscInt ii = iFace*faceSizeTet; 9077 PetscInt fVertex, cVertex; 9078 9079 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9080 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9081 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9082 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9083 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9084 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9085 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9086 faceVertices[fVertex] = origVertices[cVertex]; 9087 break; 9088 } 9089 } 9090 } 9091 found = PETSC_TRUE; 9092 break; 9093 } 9094 } 9095 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9096 if (posOriented) {*posOriented = PETSC_TRUE;} 9097 PetscFunctionReturn(0); 9098 } else if (cellDim == 3 && numCorners == 27) { 9099 /* Quadratic hexes (I hate this) 9100 A hex is two oriented quads with the normal of the first 9101 pointing up at the second. 9102 9103 7---6 9104 /| /| 9105 4---5 | 9106 | 3-|-2 9107 |/ |/ 9108 0---1 9109 9110 Faces are determined by the first 4 vertices (corners of faces) */ 9111 const PetscInt faceSizeQuadHex = 9; 9112 PetscInt sortedIndices[9], i, iFace; 9113 PetscBool found = PETSC_FALSE; 9114 PetscInt faceVerticesQuadHexSorted[54] = { 9115 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9116 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9117 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9118 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9119 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9120 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9121 }; 9122 PetscInt faceVerticesQuadHex[54] = { 9123 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9124 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9125 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9126 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9127 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9128 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9129 }; 9130 9131 faceSize = faceSizeQuadHex; 9132 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9133 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9134 for (iFace = 0; iFace < 6; ++iFace) { 9135 const PetscInt ii = iFace*faceSizeQuadHex; 9136 PetscInt fVertex, cVertex; 9137 9138 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9139 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9140 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9141 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9142 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9143 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9144 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9145 faceVertices[fVertex] = origVertices[cVertex]; 9146 break; 9147 } 9148 } 9149 } 9150 found = PETSC_TRUE; 9151 break; 9152 } 9153 } 9154 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9155 if (posOriented) {*posOriented = PETSC_TRUE;} 9156 PetscFunctionReturn(0); 9157 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9158 if (!posOrient) { 9159 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9160 for (f = 0; f < faceSize; ++f) { 9161 faceVertices[f] = origVertices[faceSize-1 - f]; 9162 } 9163 } else { 9164 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9165 for (f = 0; f < faceSize; ++f) { 9166 faceVertices[f] = origVertices[f]; 9167 } 9168 } 9169 if (posOriented) {*posOriented = posOrient;} 9170 PetscFunctionReturn(0); 9171 } 9172 9173 #undef __FUNCT__ 9174 #define __FUNCT__ "DMPlexGetOrientedFace" 9175 /* 9176 Given a cell and a face, as a set of vertices, 9177 return the oriented face, as a set of vertices, in faceVertices 9178 The orientation is such that the face normal points out of the cell 9179 */ 9180 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9181 { 9182 const PetscInt *cone = PETSC_NULL; 9183 PetscInt coneSize, v, f, v2; 9184 PetscInt oppositeVertex = -1; 9185 PetscErrorCode ierr; 9186 9187 PetscFunctionBegin; 9188 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9189 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9190 for (v = 0, v2 = 0; v < coneSize; ++v) { 9191 PetscBool found = PETSC_FALSE; 9192 9193 for (f = 0; f < faceSize; ++f) { 9194 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 9195 } 9196 if (found) { 9197 indices[v2] = v; 9198 origVertices[v2] = cone[v]; 9199 ++v2; 9200 } else { 9201 oppositeVertex = v; 9202 } 9203 } 9204 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9205 PetscFunctionReturn(0); 9206 } 9207 9208 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9209 { 9210 switch(i) { 9211 case 0: 9212 switch(j) { 9213 case 0: return 0; 9214 case 1: 9215 switch(k) { 9216 case 0: return 0; 9217 case 1: return 0; 9218 case 2: return 1; 9219 } 9220 case 2: 9221 switch(k) { 9222 case 0: return 0; 9223 case 1: return -1; 9224 case 2: return 0; 9225 } 9226 } 9227 case 1: 9228 switch(j) { 9229 case 0: 9230 switch(k) { 9231 case 0: return 0; 9232 case 1: return 0; 9233 case 2: return -1; 9234 } 9235 case 1: return 0; 9236 case 2: 9237 switch(k) { 9238 case 0: return 1; 9239 case 1: return 0; 9240 case 2: return 0; 9241 } 9242 } 9243 case 2: 9244 switch(j) { 9245 case 0: 9246 switch(k) { 9247 case 0: return 0; 9248 case 1: return 1; 9249 case 2: return 0; 9250 } 9251 case 1: 9252 switch(k) { 9253 case 0: return -1; 9254 case 1: return 0; 9255 case 2: return 0; 9256 } 9257 case 2: return 0; 9258 } 9259 } 9260 return 0; 9261 } 9262 9263 #undef __FUNCT__ 9264 #define __FUNCT__ "DMPlexCreateRigidBody" 9265 /*@C 9266 DMPlexCreateRigidBody - create rigid body modes from coordinates 9267 9268 Collective on DM 9269 9270 Input Arguments: 9271 + dm - the DM 9272 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9273 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9274 9275 Output Argument: 9276 . sp - the null space 9277 9278 Note: This is necessary to take account of Dirichlet conditions on the displacements 9279 9280 Level: advanced 9281 9282 .seealso: MatNullSpaceCreate() 9283 @*/ 9284 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9285 { 9286 MPI_Comm comm = ((PetscObject) dm)->comm; 9287 Vec coordinates, localMode, mode[6]; 9288 PetscSection coordSection; 9289 PetscScalar *coords; 9290 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9291 PetscErrorCode ierr; 9292 9293 PetscFunctionBegin; 9294 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9295 if (dim == 1) { 9296 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9297 PetscFunctionReturn(0); 9298 } 9299 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9300 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9301 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9302 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9303 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9304 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9305 m = (dim*(dim+1))/2; 9306 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9307 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9308 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9309 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9310 /* Assume P1 */ 9311 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9312 for (d = 0; d < dim; ++d) { 9313 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9314 9315 values[d] = 1.0; 9316 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9317 for (v = vStart; v < vEnd; ++v) { 9318 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9319 } 9320 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9321 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9322 } 9323 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9324 for (d = dim; d < dim*(dim+1)/2; ++d) { 9325 PetscInt i, j, k = dim > 2 ? d - dim : d; 9326 9327 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9328 for (v = vStart; v < vEnd; ++v) { 9329 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9330 PetscInt off; 9331 9332 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9333 for (i = 0; i < dim; ++i) { 9334 for (j = 0; j < dim; ++j) { 9335 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9336 } 9337 } 9338 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9339 } 9340 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9341 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9342 } 9343 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9344 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9345 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9346 /* Orthonormalize system */ 9347 for (i = dim; i < m; ++i) { 9348 PetscScalar dots[6]; 9349 9350 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9351 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9352 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9353 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9354 } 9355 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9356 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9357 PetscFunctionReturn(0); 9358 } 9359 9360 #undef __FUNCT__ 9361 #define __FUNCT__ "DMPlexGetHybridBounds" 9362 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9363 { 9364 DM_Plex *mesh = (DM_Plex *) dm->data; 9365 PetscInt dim; 9366 PetscErrorCode ierr; 9367 9368 PetscFunctionBegin; 9369 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9370 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9371 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9372 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9373 if (eMax) *eMax = mesh->hybridPointMax[1]; 9374 if (vMax) *vMax = mesh->hybridPointMax[0]; 9375 PetscFunctionReturn(0); 9376 } 9377 9378 #undef __FUNCT__ 9379 #define __FUNCT__ "DMPlexSetHybridBounds" 9380 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9381 { 9382 DM_Plex *mesh = (DM_Plex *) dm->data; 9383 PetscInt dim; 9384 PetscErrorCode ierr; 9385 9386 PetscFunctionBegin; 9387 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9388 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9389 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9390 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9391 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9392 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9393 PetscFunctionReturn(0); 9394 } 9395 9396 #undef __FUNCT__ 9397 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9398 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9399 { 9400 DM_Plex *mesh = (DM_Plex *) dm->data; 9401 9402 PetscFunctionBegin; 9403 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9404 PetscValidPointer(cellHeight, 2); 9405 *cellHeight = mesh->vtkCellHeight; 9406 PetscFunctionReturn(0); 9407 } 9408 9409 #undef __FUNCT__ 9410 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9411 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9412 { 9413 DM_Plex *mesh = (DM_Plex *) dm->data; 9414 9415 PetscFunctionBegin; 9416 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9417 mesh->vtkCellHeight = cellHeight; 9418 PetscFunctionReturn(0); 9419 } 9420 9421 #undef __FUNCT__ 9422 #define __FUNCT__ "DMPlexInsertFace_Private" 9423 /* 9424 DMPlexInsertFace_Private - Puts a face into the mesh 9425 9426 Not collective 9427 9428 Input Parameters: 9429 + dm - The DMPlex 9430 . numFaceVertex - The number of vertices in the face 9431 . faceVertices - The vertices in the face for dm 9432 . subfaceVertices - The vertices in the face for subdm 9433 . numCorners - The number of vertices in the cell 9434 . cell - A cell in dm containing the face 9435 . subcell - A cell in subdm containing the face 9436 . firstFace - First face in the mesh 9437 - newFacePoint - Next face in the mesh 9438 9439 Output Parameters: 9440 . newFacePoint - Contains next face point number on input, updated on output 9441 9442 Level: developer 9443 */ 9444 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) 9445 { 9446 MPI_Comm comm = ((PetscObject) dm)->comm; 9447 DM_Plex *submesh = (DM_Plex *) subdm->data; 9448 const PetscInt *faces; 9449 PetscInt numFaces, coneSize; 9450 PetscErrorCode ierr; 9451 9452 PetscFunctionBegin; 9453 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9454 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9455 #if 0 9456 /* Cannot use this because support() has not been constructed yet */ 9457 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9458 #else 9459 { 9460 PetscInt f; 9461 9462 numFaces = 0; 9463 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 9464 for(f = firstFace; f < *newFacePoint; ++f) { 9465 PetscInt dof, off, d; 9466 9467 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9468 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9469 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9470 for(d = 0; d < dof; ++d) { 9471 const PetscInt p = submesh->cones[off+d]; 9472 PetscInt v; 9473 9474 for(v = 0; v < numFaceVertices; ++v) { 9475 if (subfaceVertices[v] == p) break; 9476 } 9477 if (v == numFaceVertices) break; 9478 } 9479 if (d == dof) { 9480 numFaces = 1; 9481 ((PetscInt *) faces)[0] = f; 9482 } 9483 } 9484 } 9485 #endif 9486 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 9487 else if (numFaces == 1) { 9488 /* Add the other cell neighbor for this face */ 9489 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 9490 } else { 9491 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 9492 PetscBool posOriented; 9493 9494 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9495 origVertices = &orientedVertices[numFaceVertices]; 9496 indices = &orientedVertices[numFaceVertices*2]; 9497 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 9498 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 9499 /* TODO: I know that routine should return a permutation, not the indices */ 9500 for(v = 0; v < numFaceVertices; ++v) { 9501 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 9502 for(ov = 0; ov < numFaceVertices; ++ov) { 9503 if (orientedVertices[ov] == vertex) { 9504 orientedSubVertices[ov] = subvertex; 9505 break; 9506 } 9507 } 9508 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 9509 } 9510 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 9511 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 9512 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9513 ++(*newFacePoint); 9514 } 9515 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9516 PetscFunctionReturn(0); 9517 } 9518 9519 #undef __FUNCT__ 9520 #define __FUNCT__ "DMPlexCreateSubmesh" 9521 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 9522 { 9523 MPI_Comm comm = ((PetscObject) dm)->comm; 9524 DM_Plex *submesh; 9525 PetscBool boundaryFaces = PETSC_FALSE; 9526 PetscSection coordSection, subCoordSection; 9527 Vec coordinates, subCoordinates; 9528 PetscScalar *coords, *subCoords; 9529 IS labelIS; 9530 const PetscInt *subVertices; 9531 PetscInt *subVerticesActive, *tmpPoints; 9532 PetscInt *subCells = PETSC_NULL; 9533 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 9534 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 9535 PetscInt dim; /* Right now, do not specify dimension */ 9536 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 9537 PetscErrorCode ierr; 9538 9539 PetscFunctionBegin; 9540 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9541 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9542 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9543 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 9544 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9545 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9546 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9547 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9548 subface = &face[maxConeSize]; 9549 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 9550 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 9551 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 9552 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 9553 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 9554 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 9555 maxSubCells = numSubVertices; 9556 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 9557 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 9558 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 9559 for(v = 0; v < numSubVertices; ++v) { 9560 const PetscInt vertex = subVertices[v]; 9561 PetscInt *star = PETSC_NULL; 9562 PetscInt starSize, numCells = 0; 9563 9564 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9565 for(p = 0; p < starSize*2; p += 2) { 9566 const PetscInt point = star[p]; 9567 if ((point >= cStart) && (point < cEnd)) { 9568 star[numCells++] = point; 9569 } 9570 } 9571 numOldSubCells = numSubCells; 9572 for(c = 0; c < numCells; ++c) { 9573 const PetscInt cell = star[c]; 9574 PetscInt *closure = PETSC_NULL; 9575 PetscInt closureSize, numCorners = 0, faceSize = 0; 9576 PetscInt cellLoc; 9577 9578 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 9579 if (cellLoc >= 0) continue; 9580 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9581 for(p = 0; p < closureSize*2; p += 2) { 9582 const PetscInt point = closure[p]; 9583 if ((point >= vStart) && (point < vEnd)) { 9584 closure[numCorners++] = point; 9585 } 9586 } 9587 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 9588 for(corner = 0; corner < numCorners; ++corner) { 9589 const PetscInt cellVertex = closure[corner]; 9590 PetscInt subVertex; 9591 9592 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 9593 if (subVertex >= 0) { /* contains submesh vertex */ 9594 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9595 if (i == faceSize) { 9596 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 9597 face[faceSize] = cellVertex; 9598 subface[faceSize] = subVertex; 9599 ++faceSize; 9600 } 9601 } 9602 } 9603 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9604 if (faceSize >= nFV) { 9605 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9606 if (numSubCells >= maxSubCells) { 9607 PetscInt *tmpCells; 9608 maxSubCells *= 2; 9609 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 9610 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 9611 ierr = PetscFree(subCells);CHKERRQ(ierr); 9612 subCells = tmpCells; 9613 } 9614 /* TOOD: Maybe overestimate then squeeze out empty faces */ 9615 if (faceSize > nFV) { 9616 /* TODO: This is tricky. Maybe just add all faces */ 9617 numSubFaces++; 9618 } else { 9619 numSubFaces++; 9620 } 9621 for(f = 0; f < faceSize; ++f) { 9622 subVerticesActive[subface[f]] = 1; 9623 } 9624 subCells[numSubCells++] = cell; 9625 } 9626 } 9627 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9628 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 9629 } 9630 /* Pick out active subvertices */ 9631 for(v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 9632 if (subVerticesActive[v]) { 9633 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 9634 } 9635 } 9636 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 9637 /* Set cone sizes */ 9638 firstSubVertex = numSubCells; 9639 firstSubFace = numSubCells+numSubVerticesActive; 9640 newFacePoint = firstSubFace; 9641 for(c = 0; c < numSubCells; ++c) { 9642 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 9643 } 9644 for(f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 9645 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 9646 } 9647 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 9648 /* Create face cones */ 9649 for(c = 0; c < numSubCells; ++c) { 9650 const PetscInt cell = subCells[c]; 9651 PetscInt *closure = PETSC_NULL; 9652 PetscInt closureSize, numCorners = 0, faceSize = 0; 9653 9654 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9655 for(p = 0; p < closureSize*2; p += 2) { 9656 const PetscInt point = closure[p]; 9657 if ((point >= vStart) && (point < vEnd)) { 9658 closure[numCorners++] = point; 9659 } 9660 } 9661 for(corner = 0; corner < numCorners; ++corner) { 9662 const PetscInt cellVertex = closure[corner]; 9663 PetscInt subVertex; 9664 9665 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 9666 if (subVertex >= 0) { /* contains submesh vertex */ 9667 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9668 if (i == faceSize) { 9669 face[faceSize] = cellVertex; 9670 subface[faceSize] = numSubCells+subVertex; 9671 ++faceSize; 9672 } 9673 } 9674 } 9675 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9676 if (faceSize >= nFV) { 9677 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9678 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 9679 /* We have to take all the faces, and discard those in the interior */ 9680 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 9681 #if 0 9682 /* This object just calls insert on each face that comes from subsets() */ 9683 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 9684 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 9685 PointArray faceVec(face->begin(), face->end()); 9686 9687 subsets(faceVec, nFV, inserter); 9688 #endif 9689 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 9690 } 9691 } 9692 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 9693 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 9694 /* Build coordinates */ 9695 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9696 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9697 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 9698 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 9699 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 9700 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 9701 } 9702 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 9703 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 9704 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 9705 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 9706 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 9707 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9708 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9709 for(v = 0; v < numSubVerticesActive; ++v) { 9710 const PetscInt vertex = subVerticesActive[v]; 9711 const PetscInt subVertex = firstSubVertex+v; 9712 PetscInt dof, off, sdof, soff; 9713 9714 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 9715 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 9716 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 9717 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 9718 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 9719 for(d = 0; d < dof; ++d) { 9720 subCoords[soff+d] = coords[off+d]; 9721 } 9722 } 9723 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9724 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9725 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 9726 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 9727 9728 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 9729 /* Create map from submesh points to original mesh points */ 9730 submesh = (DM_Plex *) (*subdm)->data; 9731 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 9732 for(c = 0; c < numSubCells; ++c) { 9733 tmpPoints[c] = subCells[c]; 9734 } 9735 for(v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 9736 tmpPoints[v] = subVerticesActive[v-numSubCells]; 9737 } 9738 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 9739 9740 ierr = PetscFree(subCells);CHKERRQ(ierr); 9741 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 9742 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 9743 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 9744 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9745 PetscFunctionReturn(0); 9746 } 9747 9748 #undef __FUNCT__ 9749 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9750 /* We can easily have a form that takes an IS instead */ 9751 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9752 { 9753 PetscSection section, globalSection; 9754 PetscInt *numbers, p; 9755 PetscErrorCode ierr; 9756 9757 PetscFunctionBegin; 9758 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9759 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9760 for(p = pStart; p < pEnd; ++p) { 9761 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9762 } 9763 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9764 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9765 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9766 for(p = pStart; p < pEnd; ++p) { 9767 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9768 } 9769 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9770 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9771 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9772 PetscFunctionReturn(0); 9773 } 9774 9775 #undef __FUNCT__ 9776 #define __FUNCT__ "DMPlexGetCellNumbering" 9777 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9778 { 9779 DM_Plex *mesh = (DM_Plex *) dm->data; 9780 PetscInt cellHeight, cStart, cEnd, cMax; 9781 PetscErrorCode ierr; 9782 9783 PetscFunctionBegin; 9784 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9785 if (!mesh->globalCellNumbers) { 9786 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9787 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9788 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 9789 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9790 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9791 } 9792 *globalCellNumbers = mesh->globalCellNumbers; 9793 PetscFunctionReturn(0); 9794 } 9795 9796 #undef __FUNCT__ 9797 #define __FUNCT__ "DMPlexGetVertexNumbering" 9798 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9799 { 9800 DM_Plex *mesh = (DM_Plex *) dm->data; 9801 PetscInt vStart, vEnd, vMax; 9802 PetscErrorCode ierr; 9803 9804 PetscFunctionBegin; 9805 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9806 if (!mesh->globalVertexNumbers) { 9807 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9808 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9809 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9810 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9811 } 9812 *globalVertexNumbers = mesh->globalVertexNumbers; 9813 PetscFunctionReturn(0); 9814 } 9815 9816 #undef __FUNCT__ 9817 #define __FUNCT__ "DMPlexGetSubpointMap" 9818 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 9819 { 9820 DM_Plex *mesh = (DM_Plex *) dm->data; 9821 9822 PetscFunctionBegin; 9823 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9824 PetscValidPointer(subpointMap, 2); 9825 *subpointMap = mesh->subpointMap; 9826 PetscFunctionReturn(0); 9827 } 9828 9829 #undef __FUNCT__ 9830 #define __FUNCT__ "DMPlexSetSubpointMap" 9831 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 9832 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 9833 { 9834 DM_Plex *mesh = (DM_Plex *) dm->data; 9835 9836 PetscFunctionBegin; 9837 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9838 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 9839 mesh->subpointMap = subpointMap; 9840 PetscFunctionReturn(0); 9841 } 9842 9843 #undef __FUNCT__ 9844 #define __FUNCT__ "DMPlexGetScale" 9845 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9846 { 9847 DM_Plex *mesh = (DM_Plex *) dm->data; 9848 9849 PetscFunctionBegin; 9850 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9851 PetscValidPointer(scale, 3); 9852 *scale = mesh->scale[unit]; 9853 PetscFunctionReturn(0); 9854 } 9855 9856 #undef __FUNCT__ 9857 #define __FUNCT__ "DMPlexSetScale" 9858 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9859 { 9860 DM_Plex *mesh = (DM_Plex *) dm->data; 9861 9862 PetscFunctionBegin; 9863 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9864 mesh->scale[unit] = scale; 9865 PetscFunctionReturn(0); 9866 } 9867 9868 9869 /******************************************************************************* 9870 This should be in a separate Discretization object, but I am not sure how to lay 9871 it out yet, so I am stuffing things here while I experiment. 9872 *******************************************************************************/ 9873 #undef __FUNCT__ 9874 #define __FUNCT__ "DMPlexSetFEMIntegration" 9875 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9876 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9877 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9878 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9879 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9880 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9881 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9882 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9883 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9884 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9885 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9886 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9887 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9888 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9889 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9890 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9891 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9892 { 9893 DM_Plex *mesh = (DM_Plex *) dm->data; 9894 9895 PetscFunctionBegin; 9896 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9897 mesh->integrateResidualFEM = integrateResidualFEM; 9898 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9899 mesh->integrateJacobianFEM = integrateJacobianFEM; 9900 PetscFunctionReturn(0); 9901 } 9902 9903 #undef __FUNCT__ 9904 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9905 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9906 { 9907 Vec coordinates; 9908 PetscSection section, cSection; 9909 PetscInt dim, vStart, vEnd, v, c, d; 9910 PetscScalar *values, *cArray; 9911 PetscReal *coords; 9912 PetscErrorCode ierr; 9913 9914 PetscFunctionBegin; 9915 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9916 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9917 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9918 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9919 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9920 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9921 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9922 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9923 for (v = vStart; v < vEnd; ++v) { 9924 PetscInt dof, off; 9925 9926 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9927 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9928 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9929 for(d = 0; d < dof; ++d) { 9930 coords[d] = PetscRealPart(cArray[off+d]); 9931 } 9932 for(c = 0; c < numComp; ++c) { 9933 values[c] = (*funcs[c])(coords); 9934 } 9935 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9936 } 9937 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9938 /* Temporary, must be replaced by a projection on the finite element basis */ 9939 { 9940 PetscInt eStart = 0, eEnd = 0, e, depth; 9941 9942 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9943 --depth; 9944 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9945 for (e = eStart; e < eEnd; ++e) { 9946 const PetscInt *cone = PETSC_NULL; 9947 PetscInt coneSize, d; 9948 PetscScalar *coordsA, *coordsB; 9949 9950 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9951 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9952 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9953 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9954 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9955 for (d = 0; d < dim; ++d) { 9956 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9957 } 9958 for (c = 0; c < numComp; ++c) { 9959 values[c] = (*funcs[c])(coords); 9960 } 9961 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9962 } 9963 } 9964 9965 ierr = PetscFree(coords);CHKERRQ(ierr); 9966 ierr = PetscFree(values);CHKERRQ(ierr); 9967 #if 0 9968 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9969 PetscReal detJ; 9970 9971 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9972 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9973 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV((int) pow(this->_mesh->getSieve()->getMaxConeSize(), dim+1)+1, true); 9974 9975 for (PetscInt c = cStart; c < cEnd; ++c) { 9976 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9977 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9978 const int oSize = pV.getSize(); 9979 int v = 0; 9980 9981 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 9982 for (PetscInt cl = 0; cl < oSize; ++cl) { 9983 const PetscInt fDim; 9984 9985 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9986 if (pointDim) { 9987 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9988 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9989 } 9990 } 9991 } 9992 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 9993 pV.clear(); 9994 } 9995 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9996 ierr = PetscFree(values);CHKERRQ(ierr); 9997 #endif 9998 PetscFunctionReturn(0); 9999 } 10000 10001 #undef __FUNCT__ 10002 #define __FUNCT__ "DMPlexProjectFunction" 10003 /*@C 10004 DMPlexProjectFunction - This projects the given function into the function space provided. 10005 10006 Input Parameters: 10007 + dm - The DM 10008 . numComp - The number of components (functions) 10009 . funcs - The coordinate functions to evaluate 10010 - mode - The insertion mode for values 10011 10012 Output Parameter: 10013 . X - vector 10014 10015 Level: developer 10016 10017 Note: 10018 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10019 We will eventually fix it. 10020 10021 ,seealso: DMPlexComputeL2Diff() 10022 */ 10023 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10024 { 10025 Vec localX; 10026 PetscErrorCode ierr; 10027 10028 PetscFunctionBegin; 10029 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10030 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10031 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10032 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10033 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10034 PetscFunctionReturn(0); 10035 } 10036 10037 #undef __FUNCT__ 10038 #define __FUNCT__ "DMPlexComputeL2Diff" 10039 /*@C 10040 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10041 10042 Input Parameters: 10043 + dm - The DM 10044 . quad - The PetscQuadrature object for each field 10045 . funcs - The functions to evaluate for each field component 10046 - X - The coefficient vector u_h 10047 10048 Output Parameter: 10049 . diff - The diff ||u - u_h||_2 10050 10051 Level: developer 10052 10053 .seealso: DMPlexProjectFunction() 10054 */ 10055 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) { 10056 const PetscInt debug = 0; 10057 PetscSection section; 10058 Vec localX; 10059 PetscReal *coords, *v0, *J, *invJ, detJ; 10060 PetscReal localDiff = 0.0; 10061 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10062 PetscErrorCode ierr; 10063 10064 PetscFunctionBegin; 10065 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10066 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10067 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10068 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10069 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10070 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10071 for (field = 0; field < numFields; ++field) { 10072 numComponents += quad[field].numComponents; 10073 } 10074 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10075 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10076 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10077 for (c = cStart; c < cEnd; ++c) { 10078 const PetscScalar *x; 10079 PetscReal elemDiff = 0.0; 10080 10081 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10082 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10083 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10084 10085 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10086 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10087 const PetscReal *quadPoints = quad[field].quadPoints; 10088 const PetscReal *quadWeights = quad[field].quadWeights; 10089 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10090 const PetscInt numBasisComps = quad[field].numComponents; 10091 const PetscReal *basis = quad[field].basis; 10092 PetscInt q, d, e, fc, f; 10093 10094 if (debug) { 10095 char title[1024]; 10096 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10097 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10098 } 10099 for (q = 0; q < numQuadPoints; ++q) { 10100 for (d = 0; d < dim; d++) { 10101 coords[d] = v0[d]; 10102 for (e = 0; e < dim; e++) { 10103 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10104 } 10105 } 10106 for (fc = 0; fc < numBasisComps; ++fc) { 10107 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10108 PetscReal interpolant = 0.0; 10109 for (f = 0; f < numBasisFuncs; ++f) { 10110 const PetscInt fidx = f*numBasisComps+fc; 10111 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10112 } 10113 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10114 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10115 } 10116 } 10117 comp += numBasisComps; 10118 fieldOffset += numBasisFuncs*numBasisComps; 10119 } 10120 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10121 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10122 localDiff += elemDiff; 10123 } 10124 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10125 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10126 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10127 *diff = PetscSqrtReal(*diff); 10128 PetscFunctionReturn(0); 10129 } 10130 10131 #undef __FUNCT__ 10132 #define __FUNCT__ "DMPlexComputeResidualFEM" 10133 /*@ 10134 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10135 10136 Input Parameters: 10137 + dm - The mesh 10138 . X - Local input vector 10139 - user - The user context 10140 10141 Output Parameter: 10142 . F - Local output vector 10143 10144 Note: 10145 The second member of the user context must be an FEMContext. 10146 10147 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10148 like a GPU, or vectorize on a multicore machine. 10149 10150 .seealso: DMPlexComputeJacobianActionFEM() 10151 */ 10152 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10153 { 10154 DM_Plex *mesh = (DM_Plex *) dm->data; 10155 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10156 PetscQuadrature *quad = fem->quad; 10157 PetscSection section; 10158 PetscReal *v0, *J, *invJ, *detJ; 10159 PetscScalar *elemVec, *u; 10160 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10161 PetscInt cellDof = 0, numComponents = 0; 10162 PetscErrorCode ierr; 10163 10164 PetscFunctionBegin; 10165 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10166 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10167 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10168 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10169 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10170 numCells = cEnd - cStart; 10171 for (field = 0; field < numFields; ++field) { 10172 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10173 numComponents += quad[field].numComponents; 10174 } 10175 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10176 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10177 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); 10178 for (c = cStart; c < cEnd; ++c) { 10179 const PetscScalar *x; 10180 PetscInt i; 10181 10182 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10183 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10184 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10185 10186 for (i = 0; i < cellDof; ++i) { 10187 u[c*cellDof+i] = x[i]; 10188 } 10189 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10190 } 10191 for (field = 0; field < numFields; ++field) { 10192 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10193 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10194 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10195 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10196 /* Conforming batches */ 10197 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10198 PetscInt numBlocks = 1; 10199 PetscInt batchSize = numBlocks * blockSize; 10200 PetscInt numBatches = numBatchesTmp; 10201 PetscInt numChunks = numCells / (numBatches*batchSize); 10202 /* Remainder */ 10203 PetscInt numRemainder = numCells % (numBatches * batchSize); 10204 PetscInt offset = numCells - numRemainder; 10205 10206 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10207 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10208 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10209 } 10210 for (c = cStart; c < cEnd; ++c) { 10211 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10212 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10213 } 10214 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10215 if (mesh->printFEM) { 10216 PetscMPIInt rank, numProcs; 10217 PetscInt p; 10218 10219 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10220 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10221 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10222 for (p = 0; p < numProcs; ++p) { 10223 if (p == rank) { 10224 Vec f; 10225 10226 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10227 ierr = VecCopy(F, f);CHKERRQ(ierr); 10228 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10229 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10230 ierr = VecDestroy(&f);CHKERRQ(ierr); 10231 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10232 } 10233 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10234 } 10235 } 10236 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10237 PetscFunctionReturn(0); 10238 } 10239 10240 #undef __FUNCT__ 10241 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10242 /*@C 10243 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10244 10245 Input Parameters: 10246 + dm - The mesh 10247 . J - The Jacobian shell matrix 10248 . X - Local input vector 10249 - user - The user context 10250 10251 Output Parameter: 10252 . F - Local output vector 10253 10254 Note: 10255 The second member of the user context must be an FEMContext. 10256 10257 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10258 like a GPU, or vectorize on a multicore machine. 10259 10260 .seealso: DMPlexComputeResidualFEM() 10261 */ 10262 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10263 { 10264 DM_Plex *mesh = (DM_Plex *) dm->data; 10265 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10266 PetscQuadrature *quad = fem->quad; 10267 PetscSection section; 10268 JacActionCtx *jctx; 10269 PetscReal *v0, *J, *invJ, *detJ; 10270 PetscScalar *elemVec, *u, *a; 10271 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10272 PetscInt cellDof = 0; 10273 PetscErrorCode ierr; 10274 10275 PetscFunctionBegin; 10276 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10277 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10278 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10279 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10280 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10281 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10282 numCells = cEnd - cStart; 10283 for (field = 0; field < numFields; ++field) { 10284 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10285 } 10286 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10287 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); 10288 for (c = cStart; c < cEnd; ++c) { 10289 const PetscScalar *x; 10290 PetscInt i; 10291 10292 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10293 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10294 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10295 for (i = 0; i < cellDof; ++i) { 10296 u[c*cellDof+i] = x[i]; 10297 } 10298 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10299 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10300 for (i = 0; i < cellDof; ++i) { 10301 a[c*cellDof+i] = x[i]; 10302 } 10303 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10304 } 10305 for (field = 0; field < numFields; ++field) { 10306 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10307 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10308 /* Conforming batches */ 10309 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10310 PetscInt numBlocks = 1; 10311 PetscInt batchSize = numBlocks * blockSize; 10312 PetscInt numBatches = numBatchesTmp; 10313 PetscInt numChunks = numCells / (numBatches*batchSize); 10314 /* Remainder */ 10315 PetscInt numRemainder = numCells % (numBatches * batchSize); 10316 PetscInt offset = numCells - numRemainder; 10317 10318 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); 10319 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], 10320 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10321 } 10322 for (c = cStart; c < cEnd; ++c) { 10323 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10324 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10325 } 10326 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10327 if (mesh->printFEM) { 10328 PetscMPIInt rank, numProcs; 10329 PetscInt p; 10330 10331 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10332 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10333 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10334 for (p = 0; p < numProcs; ++p) { 10335 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10336 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10337 } 10338 } 10339 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10340 PetscFunctionReturn(0); 10341 } 10342 10343 #undef __FUNCT__ 10344 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10345 /*@ 10346 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10347 10348 Input Parameters: 10349 + dm - The mesh 10350 . X - Local input vector 10351 - user - The user context 10352 10353 Output Parameter: 10354 . Jac - Jacobian matrix 10355 10356 Note: 10357 The second member of the user context must be an FEMContext. 10358 10359 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10360 like a GPU, or vectorize on a multicore machine. 10361 10362 .seealso: FormFunctionLocal() 10363 */ 10364 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10365 { 10366 DM_Plex *mesh = (DM_Plex *) dm->data; 10367 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10368 PetscQuadrature *quad = fem->quad; 10369 PetscSection section; 10370 PetscReal *v0, *J, *invJ, *detJ; 10371 PetscScalar *elemMat, *u; 10372 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10373 PetscInt cellDof = 0, numComponents = 0; 10374 PetscBool isShell; 10375 PetscErrorCode ierr; 10376 10377 PetscFunctionBegin; 10378 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10379 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10380 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10381 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10382 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10383 numCells = cEnd - cStart; 10384 for (field = 0; field < numFields; ++field) { 10385 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10386 numComponents += quad[field].numComponents; 10387 } 10388 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10389 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10390 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); 10391 for (c = cStart; c < cEnd; ++c) { 10392 const PetscScalar *x; 10393 PetscInt i; 10394 10395 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10396 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10397 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10398 10399 for (i = 0; i < cellDof; ++i) { 10400 u[c*cellDof+i] = x[i]; 10401 } 10402 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10403 } 10404 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10405 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10406 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10407 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10408 PetscInt fieldJ; 10409 10410 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10411 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10412 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10413 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10414 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10415 /* Conforming batches */ 10416 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10417 PetscInt numBlocks = 1; 10418 PetscInt batchSize = numBlocks * blockSize; 10419 PetscInt numBatches = numBatchesTmp; 10420 PetscInt numChunks = numCells / (numBatches*batchSize); 10421 /* Remainder */ 10422 PetscInt numRemainder = numCells % (numBatches * batchSize); 10423 PetscInt offset = numCells - numRemainder; 10424 10425 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10426 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10427 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10428 } 10429 } 10430 for (c = cStart; c < cEnd; ++c) { 10431 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10432 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10433 } 10434 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10435 10436 /* Assemble matrix, using the 2-step process: 10437 MatAssemblyBegin(), MatAssemblyEnd(). */ 10438 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10439 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10440 10441 if (mesh->printFEM) { 10442 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10443 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10444 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10445 } 10446 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10447 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10448 if (isShell) { 10449 JacActionCtx *jctx; 10450 10451 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10452 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10453 } 10454 *str = SAME_NONZERO_PATTERN; 10455 PetscFunctionReturn(0); 10456 } 10457 10458 10459 #undef __FUNCT__ 10460 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10461 /*@C 10462 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10463 the local section and an SF describing the section point overlap. 10464 10465 Input Parameters: 10466 + s - The PetscSection for the local field layout 10467 . sf - The SF describing parallel layout of the section points 10468 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10469 . label - The label specifying the points 10470 - labelValue - The label stratum specifying the points 10471 10472 Output Parameter: 10473 . gsection - The PetscSection for the global field layout 10474 10475 Note: This gives negative sizes and offsets to points not owned by this process 10476 10477 Level: developer 10478 10479 .seealso: PetscSectionCreate() 10480 @*/ 10481 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10482 { 10483 PetscInt *neg; 10484 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10485 PetscErrorCode ierr; 10486 10487 PetscFunctionBegin; 10488 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10489 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10490 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10491 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10492 /* Mark ghost points with negative dof */ 10493 for (p = pStart; p < pEnd; ++p) { 10494 PetscInt value; 10495 10496 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 10497 if (value != labelValue) continue; 10498 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 10499 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 10500 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 10501 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 10502 neg[p-pStart] = -(dof+1); 10503 } 10504 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 10505 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10506 if (nroots >= 0) { 10507 if (nroots > pEnd - pStart) { 10508 PetscInt *tmpDof; 10509 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10510 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 10511 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10512 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10513 for (p = pStart; p < pEnd; ++p) { 10514 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 10515 } 10516 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 10517 } else { 10518 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10519 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10520 } 10521 } 10522 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 10523 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10524 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 10525 (*gsection)->atlasOff[p] = off; 10526 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 10527 } 10528 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 10529 globalOff -= off; 10530 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10531 (*gsection)->atlasOff[p] += globalOff; 10532 neg[p] = -((*gsection)->atlasOff[p]+1); 10533 } 10534 /* Put in negative offsets for ghost points */ 10535 if (nroots >= 0) { 10536 if (nroots > pEnd - pStart) { 10537 PetscInt *tmpOff; 10538 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10539 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 10540 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10541 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10542 for (p = pStart; p < pEnd; ++p) { 10543 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 10544 } 10545 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 10546 } else { 10547 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10548 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10549 } 10550 } 10551 ierr = PetscFree(neg);CHKERRQ(ierr); 10552 PetscFunctionReturn(0); 10553 } 10554