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 = PetscOListDuplicate(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 const PetscInt maxFaceCases = 30; 2556 PetscInt numFaceCases = 0; 2557 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2558 PetscInt *off, *adj; 2559 PetscInt *neighborCells, *tmpClosure; 2560 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2561 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2562 PetscErrorCode ierr; 2563 2564 PetscFunctionBegin; 2565 /* For parallel partitioning, I think you have to communicate supports */ 2566 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2567 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2568 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2569 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2570 if (cEnd - cStart == 0) { 2571 if (numVertices) *numVertices = 0; 2572 if (offsets) *offsets = PETSC_NULL; 2573 if (adjacency) *adjacency = PETSC_NULL; 2574 PetscFunctionReturn(0); 2575 } 2576 numCells = cEnd - cStart; 2577 /* Setup face recognition */ 2578 { 2579 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 */ 2580 2581 for (c = cStart; c < cEnd; ++c) { 2582 PetscInt corners; 2583 2584 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2585 if (!cornersSeen[corners]) { 2586 PetscInt nFV; 2587 2588 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2589 cornersSeen[corners] = 1; 2590 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2591 numFaceVertices[numFaceCases++] = nFV; 2592 } 2593 } 2594 } 2595 maxClosure = (PetscInt) (2*PetscMax(pow((PetscReal) maxConeSize, depth)+1, pow((PetscReal) maxSupportSize, depth)+1)); 2596 maxNeighbors = (PetscInt) (pow((PetscReal) maxConeSize, depth)*pow((PetscReal) maxSupportSize, depth)+1); 2597 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2598 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2599 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2600 /* Count neighboring cells */ 2601 for (cell = cStart; cell < cEnd; ++cell) { 2602 PetscInt numNeighbors = maxNeighbors, n; 2603 2604 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2605 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2606 for (n = 0; n < numNeighbors; ++n) { 2607 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2608 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2609 PetscInt meetSize = 0; 2610 const PetscInt *meet = PETSC_NULL; 2611 2612 if (cellPair[0] == cellPair[1]) continue; 2613 if (!found) { 2614 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2615 if (meetSize) { 2616 PetscInt f; 2617 2618 for (f = 0; f < numFaceCases; ++f) { 2619 if (numFaceVertices[f] == meetSize) { 2620 found = PETSC_TRUE; 2621 break; 2622 } 2623 } 2624 } 2625 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2626 } 2627 if (found) { 2628 ++off[cell-cStart+1]; 2629 } 2630 } 2631 } 2632 /* Prefix sum */ 2633 for (cell = 1; cell <= numCells; ++cell) { 2634 off[cell] += off[cell-1]; 2635 } 2636 if (adjacency) { 2637 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2638 /* Get neighboring cells */ 2639 for (cell = cStart; cell < cEnd; ++cell) { 2640 PetscInt numNeighbors = maxNeighbors, n; 2641 PetscInt cellOffset = 0; 2642 2643 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2644 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2645 for (n = 0; n < numNeighbors; ++n) { 2646 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2647 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2648 PetscInt meetSize = 0; 2649 const PetscInt *meet = PETSC_NULL; 2650 2651 if (cellPair[0] == cellPair[1]) continue; 2652 if (!found) { 2653 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2654 if (meetSize) { 2655 PetscInt f; 2656 2657 for (f = 0; f < numFaceCases; ++f) { 2658 if (numFaceVertices[f] == meetSize) { 2659 found = PETSC_TRUE; 2660 break; 2661 } 2662 } 2663 } 2664 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2665 } 2666 if (found) { 2667 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2668 ++cellOffset; 2669 } 2670 } 2671 } 2672 } 2673 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2674 if (numVertices) *numVertices = numCells; 2675 if (offsets) *offsets = off; 2676 if (adjacency) *adjacency = adj; 2677 PetscFunctionReturn(0); 2678 } 2679 2680 #ifdef PETSC_HAVE_CHACO 2681 #ifdef PETSC_HAVE_UNISTD_H 2682 #include <unistd.h> 2683 #endif 2684 /* Chaco does not have an include file */ 2685 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2686 float *ewgts, float *x, float *y, float *z, char *outassignname, 2687 char *outfilename, short *assignment, int architecture, int ndims_tot, 2688 int mesh_dims[3], double *goal, int global_method, int local_method, 2689 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2690 2691 extern int FREE_GRAPH; 2692 2693 #undef __FUNCT__ 2694 #define __FUNCT__ "DMPlexPartition_Chaco" 2695 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2696 { 2697 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2698 MPI_Comm comm = ((PetscObject) dm)->comm; 2699 int nvtxs = numVertices; /* number of vertices in full graph */ 2700 int *vwgts = NULL; /* weights for all vertices */ 2701 float *ewgts = NULL; /* weights for all edges */ 2702 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2703 char *outassignname = NULL; /* name of assignment output file */ 2704 char *outfilename = NULL; /* output file name */ 2705 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2706 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2707 int mesh_dims[3]; /* dimensions of mesh of processors */ 2708 double *goal = NULL; /* desired set sizes for each set */ 2709 int global_method = 1; /* global partitioning algorithm */ 2710 int local_method = 1; /* local partitioning algorithm */ 2711 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2712 int vmax = 200; /* how many vertices to coarsen down to? */ 2713 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2714 double eigtol = 0.001; /* tolerance on eigenvectors */ 2715 long seed = 123636512; /* for random graph mutations */ 2716 short int *assignment; /* Output partition */ 2717 int fd_stdout, fd_pipe[2]; 2718 PetscInt *points; 2719 PetscMPIInt commSize; 2720 int i, v, p; 2721 PetscErrorCode ierr; 2722 2723 PetscFunctionBegin; 2724 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2725 if (!numVertices) { 2726 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2727 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2728 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2729 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2730 PetscFunctionReturn(0); 2731 } 2732 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2733 for (i = 0; i < start[numVertices]; ++i) { 2734 ++adjacency[i]; 2735 } 2736 if (global_method == INERTIAL_METHOD) { 2737 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2738 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2739 } 2740 mesh_dims[0] = commSize; 2741 mesh_dims[1] = 1; 2742 mesh_dims[2] = 1; 2743 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2744 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2745 /* TODO: check error codes for UNIX calls */ 2746 #ifdef PETSC_HAVE_UNISTD_H 2747 { 2748 int piperet; 2749 piperet = pipe(fd_pipe); 2750 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2751 fd_stdout = dup(1); 2752 close(1); 2753 dup2(fd_pipe[1], 1); 2754 } 2755 #endif 2756 ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2757 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2758 vmax, ndims, eigtol, seed); 2759 #ifdef PETSC_HAVE_UNISTD_H 2760 { 2761 char msgLog[10000]; 2762 int count; 2763 2764 fflush(stdout); 2765 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2766 if (count < 0) count = 0; 2767 msgLog[count] = 0; 2768 close(1); 2769 dup2(fd_stdout, 1); 2770 close(fd_stdout); 2771 close(fd_pipe[0]); 2772 close(fd_pipe[1]); 2773 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2774 } 2775 #endif 2776 /* Convert to PetscSection+IS */ 2777 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2778 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2779 for (v = 0; v < nvtxs; ++v) { 2780 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2781 } 2782 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2783 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2784 for (p = 0, i = 0; p < commSize; ++p) { 2785 for (v = 0; v < nvtxs; ++v) { 2786 if (assignment[v] == p) points[i++] = v; 2787 } 2788 } 2789 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2790 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2791 if (global_method == INERTIAL_METHOD) { 2792 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2793 } 2794 ierr = PetscFree(assignment);CHKERRQ(ierr); 2795 for (i = 0; i < start[numVertices]; ++i) { 2796 --adjacency[i]; 2797 } 2798 PetscFunctionReturn(0); 2799 } 2800 #endif 2801 2802 #ifdef PETSC_HAVE_PARMETIS 2803 #undef __FUNCT__ 2804 #define __FUNCT__ "DMPlexPartition_ParMetis" 2805 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2806 { 2807 PetscFunctionBegin; 2808 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2809 PetscFunctionReturn(0); 2810 } 2811 #endif 2812 2813 #undef __FUNCT__ 2814 #define __FUNCT__ "DMPlexEnlargePartition" 2815 /* Expand the partition by BFS on the adjacency graph */ 2816 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) { 2817 PetscHashI h; 2818 const PetscInt *points; 2819 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2820 PetscInt pStart, pEnd, part, q; 2821 PetscErrorCode ierr; 2822 2823 PetscFunctionBegin; 2824 PetscHashICreate(h); 2825 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2826 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2827 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2828 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2829 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2830 for(part = pStart; part < pEnd; ++part) { 2831 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2832 2833 PetscHashIClear(h); 2834 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2835 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2836 /* Add all existing points to h */ 2837 for(p = 0; p < numPoints; ++p) { 2838 const PetscInt point = points[off+p]; 2839 PetscHashIAdd(h, point, 1); 2840 } 2841 PetscHashISize(h, nP); 2842 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2843 /* Add all points in next BFS level */ 2844 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2845 for(p = 0; p < numPoints; ++p) { 2846 const PetscInt point = points[off+p]; 2847 PetscInt s = start[point], e = start[point+1], a; 2848 2849 for(a = s; a < e; ++a) { 2850 PetscHashIAdd(h, adjacency[a], 1); 2851 } 2852 } 2853 PetscHashISize(h, numNewPoints); 2854 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2855 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2856 if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2857 totPoints += numNewPoints; 2858 } 2859 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2860 PetscHashIDestroy(h); 2861 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2862 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2863 for(part = pStart, q = 0; part < pEnd; ++part) { 2864 PetscInt numPoints, p; 2865 2866 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2867 for(p = 0; p < numPoints; ++p, ++q) { 2868 newPoints[q] = tmpPoints[part][p]; 2869 } 2870 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2871 } 2872 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2873 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2874 PetscFunctionReturn(0); 2875 } 2876 2877 #undef __FUNCT__ 2878 #define __FUNCT__ "DMPlexCreatePartition" 2879 /* 2880 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2881 2882 Collective on DM 2883 2884 Input Parameters: 2885 + dm - The DM 2886 . height - The height for points in the partition 2887 - enlarge - Expand each partition with neighbors 2888 2889 Output Parameters: 2890 + partSection - The PetscSection giving the division of points by partition 2891 . partition - The list of points by partition 2892 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2893 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2894 2895 Level: developer 2896 2897 .seealso DMPlexDistribute() 2898 */ 2899 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) { 2900 PetscMPIInt size; 2901 PetscErrorCode ierr; 2902 2903 PetscFunctionBegin; 2904 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2905 *origPartSection = PETSC_NULL; 2906 *origPartition = PETSC_NULL; 2907 if (size == 1) { 2908 PetscInt *points; 2909 PetscInt cStart, cEnd, c; 2910 2911 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2912 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2913 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2914 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2915 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2916 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2917 for (c = cStart; c < cEnd; ++c) { 2918 points[c] = c; 2919 } 2920 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2921 PetscFunctionReturn(0); 2922 } 2923 if (height == 0) { 2924 PetscInt numVertices; 2925 PetscInt *start = PETSC_NULL; 2926 PetscInt *adjacency = PETSC_NULL; 2927 2928 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2929 if (1) { 2930 #ifdef PETSC_HAVE_CHACO 2931 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2932 #endif 2933 } else { 2934 #ifdef PETSC_HAVE_PARMETIS 2935 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2936 #endif 2937 } 2938 if (enlarge) { 2939 *origPartSection = *partSection; 2940 *origPartition = *partition; 2941 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2942 } 2943 ierr = PetscFree(start);CHKERRQ(ierr); 2944 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2945 # if 0 2946 } else if (height == 1) { 2947 /* Build the dual graph for faces and partition the hypergraph */ 2948 PetscInt numEdges; 2949 2950 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2951 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2952 destroyCSR(numEdges, start, adjacency); 2953 #endif 2954 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2955 PetscFunctionReturn(0); 2956 } 2957 2958 #undef __FUNCT__ 2959 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2960 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) { 2961 /* const PetscInt height = 0; */ 2962 const PetscInt *partArray; 2963 PetscInt *allPoints, *partPoints = PETSC_NULL; 2964 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2965 PetscErrorCode ierr; 2966 2967 PetscFunctionBegin; 2968 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2969 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2970 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2971 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2972 for (rank = rStart; rank < rEnd; ++rank) { 2973 PetscInt partSize = 0; 2974 PetscInt numPoints, offset, p; 2975 2976 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2977 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2978 for (p = 0; p < numPoints; ++p) { 2979 PetscInt point = partArray[offset+p], closureSize, c; 2980 PetscInt *closure = PETSC_NULL; 2981 2982 /* TODO Include support for height > 0 case */ 2983 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2984 /* Merge into existing points */ 2985 if (partSize+closureSize > maxPartSize) { 2986 PetscInt *tmpPoints; 2987 2988 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2989 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2990 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2991 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2992 partPoints = tmpPoints; 2993 } 2994 for (c = 0; c < closureSize; ++c) { 2995 partPoints[partSize+c] = closure[c*2]; 2996 } 2997 partSize += closureSize; 2998 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 2999 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3000 } 3001 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3002 } 3003 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3004 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3005 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3006 3007 for (rank = rStart; rank < rEnd; ++rank) { 3008 PetscInt partSize = 0, newOffset; 3009 PetscInt numPoints, offset, p; 3010 3011 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3012 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3013 for (p = 0; p < numPoints; ++p) { 3014 PetscInt point = partArray[offset+p], closureSize, c; 3015 PetscInt *closure = PETSC_NULL; 3016 3017 /* TODO Include support for height > 0 case */ 3018 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3019 /* Merge into existing points */ 3020 for (c = 0; c < closureSize; ++c) { 3021 partPoints[partSize+c] = closure[c*2]; 3022 } 3023 partSize += closureSize; 3024 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3025 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3026 } 3027 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3028 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3029 } 3030 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3031 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3032 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3033 PetscFunctionReturn(0); 3034 } 3035 3036 #undef __FUNCT__ 3037 #define __FUNCT__ "DMPlexDistributeField" 3038 /* 3039 Input Parameters: 3040 . originalSection 3041 , originalVec 3042 3043 Output Parameters: 3044 . newSection 3045 . newVec 3046 */ 3047 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3048 { 3049 PetscSF fieldSF; 3050 PetscInt *remoteOffsets, fieldSize; 3051 PetscScalar *originalValues, *newValues; 3052 PetscErrorCode ierr; 3053 3054 PetscFunctionBegin; 3055 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3056 3057 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3058 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3059 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3060 3061 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3062 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3063 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3064 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3065 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3066 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3067 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3068 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3069 PetscFunctionReturn(0); 3070 } 3071 3072 #undef __FUNCT__ 3073 #define __FUNCT__ "DMPlexDistribute" 3074 /*@C 3075 DMPlexDistribute - Distributes the mesh and any associated sections. 3076 3077 Not Collective 3078 3079 Input Parameter: 3080 + dm - The original DMPlex object 3081 . partitioner - The partitioning package, or NULL for the default 3082 - overlap - The overlap of partitions, 0 is the default 3083 3084 Output Parameter: 3085 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3086 3087 Note: If the mesh was not distributed, the return value is PETSC_NULL 3088 3089 Level: intermediate 3090 3091 .keywords: mesh, elements 3092 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3093 @*/ 3094 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3095 { 3096 DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3097 MPI_Comm comm = ((PetscObject) dm)->comm; 3098 const PetscInt height = 0; 3099 PetscInt dim, numRemoteRanks; 3100 IS origCellPart, cellPart, part; 3101 PetscSection origCellPartSection, cellPartSection, partSection; 3102 PetscSFNode *remoteRanks; 3103 PetscSF partSF, pointSF, coneSF; 3104 ISLocalToGlobalMapping renumbering; 3105 PetscSection originalConeSection, newConeSection; 3106 PetscInt *remoteOffsets; 3107 PetscInt *cones, *newCones, newConesSize; 3108 PetscBool flg; 3109 PetscMPIInt rank, numProcs, p; 3110 PetscErrorCode ierr; 3111 3112 PetscFunctionBegin; 3113 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3114 PetscValidPointer(dmParallel,4); 3115 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3116 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3117 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3118 *dmParallel = PETSC_NULL; 3119 if (numProcs == 1) PetscFunctionReturn(0); 3120 3121 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3122 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3123 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3124 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3125 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3126 if (!rank) { 3127 numRemoteRanks = numProcs; 3128 } else { 3129 numRemoteRanks = 0; 3130 } 3131 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3132 for (p = 0; p < numRemoteRanks; ++p) { 3133 remoteRanks[p].rank = p; 3134 remoteRanks[p].index = 0; 3135 } 3136 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3137 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3138 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3139 if (flg) { 3140 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3141 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3142 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3143 if (origCellPart) { 3144 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3145 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3146 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3147 } 3148 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3149 } 3150 /* Close the partition over the mesh */ 3151 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3152 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3153 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3154 /* Create new mesh */ 3155 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3156 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3157 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3158 pmesh = (DM_Plex *) (*dmParallel)->data; 3159 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3160 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3161 if (flg) { 3162 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3163 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3164 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3165 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3166 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3167 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3168 } 3169 /* Distribute cone section */ 3170 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3171 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3172 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3173 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3174 { 3175 PetscInt pStart, pEnd, p; 3176 3177 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3178 for (p = pStart; p < pEnd; ++p) { 3179 PetscInt coneSize; 3180 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3181 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3182 } 3183 } 3184 /* Communicate and renumber cones */ 3185 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3186 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3187 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3188 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3189 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3190 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3191 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3192 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3193 if (flg) { 3194 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3195 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3196 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3197 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3198 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3199 } 3200 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3201 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3202 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3203 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3204 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3205 /* Create supports and stratify sieve */ 3206 { 3207 PetscInt pStart, pEnd; 3208 3209 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3210 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3211 } 3212 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3213 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3214 /* Distribute Coordinates */ 3215 { 3216 PetscSection originalCoordSection, newCoordSection; 3217 Vec originalCoordinates, newCoordinates; 3218 const char *name; 3219 3220 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3221 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3222 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3223 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3224 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3225 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3226 3227 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3228 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3229 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3230 } 3231 /* Distribute labels */ 3232 { 3233 DMLabel next = mesh->labels, newNext = pmesh->labels; 3234 PetscInt numLabels = 0, l; 3235 3236 /* Bcast number of labels */ 3237 while(next) {++numLabels; next = next->next;} 3238 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3239 next = mesh->labels; 3240 for (l = 0; l < numLabels; ++l) { 3241 DMLabel newLabel; 3242 const PetscInt *partArray; 3243 char *name; 3244 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3245 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3246 PetscInt nameSize, s, p; 3247 PetscBool isdepth; 3248 size_t len = 0; 3249 3250 /* Bcast name (could filter for no points) */ 3251 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3252 nameSize = len; 3253 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3254 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3255 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3256 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3257 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3258 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3259 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3260 newLabel->name = name; 3261 /* Bcast numStrata (could filter for no points in stratum) */ 3262 if (!rank) {newLabel->numStrata = next->numStrata;} 3263 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3264 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3265 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3266 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3267 /* Bcast stratumValues (could filter for no points in stratum) */ 3268 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3269 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3270 /* Find size on each process and Scatter */ 3271 if (!rank) { 3272 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3273 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3274 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3275 for (s = 0; s < next->numStrata; ++s) { 3276 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3277 const PetscInt point = next->points[p]; 3278 PetscInt proc; 3279 3280 for (proc = 0; proc < numProcs; ++proc) { 3281 PetscInt dof, off, pPart; 3282 3283 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3284 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3285 for (pPart = off; pPart < off+dof; ++pPart) { 3286 if (partArray[pPart] == point) { 3287 ++stratumSizes[proc*next->numStrata+s]; 3288 break; 3289 } 3290 } 3291 } 3292 } 3293 } 3294 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3295 } 3296 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3297 /* Calculate stratumOffsets */ 3298 newLabel->stratumOffsets[0] = 0; 3299 for (s = 0; s < newLabel->numStrata; ++s) { 3300 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3301 } 3302 /* Pack points and Scatter */ 3303 if (!rank) { 3304 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3305 displs[0] = 0; 3306 for (p = 0; p < numProcs; ++p) { 3307 sendcnts[p] = 0; 3308 for (s = 0; s < next->numStrata; ++s) { 3309 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3310 } 3311 offsets[p] = displs[p]; 3312 displs[p+1] = displs[p] + sendcnts[p]; 3313 } 3314 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3315 for (s = 0; s < next->numStrata; ++s) { 3316 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3317 const PetscInt point = next->points[p]; 3318 PetscInt proc; 3319 3320 for (proc = 0; proc < numProcs; ++proc) { 3321 PetscInt dof, off, pPart; 3322 3323 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3324 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3325 for (pPart = off; pPart < off+dof; ++pPart) { 3326 if (partArray[pPart] == point) { 3327 points[offsets[proc]++] = point; 3328 break; 3329 } 3330 } 3331 } 3332 } 3333 } 3334 } 3335 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3336 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3337 ierr = PetscFree(points);CHKERRQ(ierr); 3338 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3339 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3340 /* Renumber points */ 3341 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3342 /* Sort points */ 3343 for (s = 0; s < newLabel->numStrata; ++s) { 3344 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3345 } 3346 /* Insert into list */ 3347 if (newNext) { 3348 newNext->next = newLabel; 3349 } else { 3350 pmesh->labels = newLabel; 3351 } 3352 newNext = newLabel; 3353 if (!rank) {next = next->next;} 3354 } 3355 } 3356 /* Cleanup Partition */ 3357 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3358 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3359 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3360 ierr = ISDestroy(&part);CHKERRQ(ierr); 3361 /* Create point SF for parallel mesh */ 3362 { 3363 const PetscInt *leaves; 3364 PetscSFNode *remotePoints, *rowners, *lowners; 3365 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3366 PetscInt pStart, pEnd; 3367 3368 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3369 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3370 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3371 for (p=0; p<numRoots; p++) { 3372 rowners[p].rank = -1; 3373 rowners[p].index = -1; 3374 } 3375 if (origCellPart) { 3376 /* Make sure cells in the original partition are not assigned to other procs */ 3377 const PetscInt *origCells; 3378 3379 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3380 for (p = 0; p < numProcs; ++p) { 3381 PetscInt dof, off, d; 3382 3383 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3384 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3385 for(d = off; d < off+dof; ++d) { 3386 rowners[origCells[d]].rank = p; 3387 } 3388 } 3389 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3390 } 3391 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3392 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3393 3394 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3395 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3396 for (p = 0; p < numLeaves; ++p) { 3397 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3398 lowners[p].rank = rank; 3399 lowners[p].index = leaves ? leaves[p] : p; 3400 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3401 lowners[p].rank = -2; 3402 lowners[p].index = -2; 3403 } 3404 } 3405 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3406 rowners[p].rank = -3; 3407 rowners[p].index = -3; 3408 } 3409 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3410 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3411 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3412 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3413 for (p = 0; p < numLeaves; ++p) { 3414 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3415 if (lowners[p].rank != rank) ++numGhostPoints; 3416 } 3417 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3418 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3419 for (p = 0, gp = 0; p < numLeaves; ++p) { 3420 if (lowners[p].rank != rank) { 3421 ghostPoints[gp] = leaves ? leaves[p] : p; 3422 remotePoints[gp].rank = lowners[p].rank; 3423 remotePoints[gp].index = lowners[p].index; 3424 ++gp; 3425 } 3426 } 3427 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3428 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3429 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3430 } 3431 /* Cleanup */ 3432 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3433 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3434 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3435 PetscFunctionReturn(0); 3436 } 3437 3438 #undef __FUNCT__ 3439 #define __FUNCT__ "DMPlexRenumber_Private" 3440 /* 3441 Reasons to renumber: 3442 3443 1) Permute points, e.g. bandwidth reduction (Renumber) 3444 3445 a) Must not mix strata 3446 3447 2) Shift numbers for point insertion (Shift) 3448 3449 a) Want operation brken into parts so that insertion can be interleaved 3450 3451 renumbering - An IS which provides the new numbering 3452 */ 3453 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3454 { 3455 PetscFunctionBegin; 3456 PetscFunctionReturn(0); 3457 } 3458 3459 #undef __FUNCT__ 3460 #define __FUNCT__ "DMPlexShiftPoint_Private" 3461 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3462 { 3463 if (depth < 0) return p; 3464 /* Cells */ if (p < depthEnd[depth]) return p; 3465 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3466 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3467 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3468 } 3469 3470 #undef __FUNCT__ 3471 #define __FUNCT__ "DMPlexShiftSizes_Private" 3472 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3473 { 3474 PetscInt *depthEnd; 3475 PetscInt depth = 0, d, pStart, pEnd, p; 3476 PetscErrorCode ierr; 3477 3478 PetscFunctionBegin; 3479 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3480 if (depth < 0) PetscFunctionReturn(0); 3481 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3482 /* Step 1: Expand chart */ 3483 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3484 for(d = 0; d <= depth; ++d) { 3485 pEnd += depthShift[d]; 3486 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3487 } 3488 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3489 /* Step 2: Set cone and support sizes */ 3490 for(d = 0; d <= depth; ++d) { 3491 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3492 for(p = pStart; p < pEnd; ++p) { 3493 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3494 PetscInt size; 3495 3496 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3497 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3498 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3499 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3500 } 3501 } 3502 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3503 PetscFunctionReturn(0); 3504 } 3505 3506 #undef __FUNCT__ 3507 #define __FUNCT__ "DMPlexShiftPoints_Private" 3508 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3509 { 3510 PetscInt *depthEnd, *newpoints; 3511 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3512 PetscErrorCode ierr; 3513 3514 PetscFunctionBegin; 3515 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3516 if (depth < 0) PetscFunctionReturn(0); 3517 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3518 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3519 for(d = 0; d <= depth; ++d) { 3520 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3521 } 3522 /* Step 5: Set cones and supports */ 3523 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3524 for(p = pStart; p < pEnd; ++p) { 3525 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3526 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3527 3528 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3529 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3530 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3531 for(i = 0; i < size; ++i) { 3532 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3533 } 3534 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3535 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3536 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3537 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3538 for(i = 0; i < size; ++i) { 3539 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3540 } 3541 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3542 } 3543 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3544 PetscFunctionReturn(0); 3545 } 3546 3547 #undef __FUNCT__ 3548 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3549 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3550 { 3551 PetscSection coordSection, newCoordSection; 3552 Vec coordinates; 3553 PetscInt *depthEnd; 3554 PetscInt dim, depth = 0, d, vStart, vEnd, v; 3555 PetscErrorCode ierr; 3556 3557 PetscFunctionBegin; 3558 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3559 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3560 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3561 for(d = 0; d <= depth; ++d) { 3562 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3563 } 3564 /* Step 8: Convert coordinates */ 3565 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3566 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3567 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3568 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3569 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3570 ierr = PetscSectionSetChart(newCoordSection, DMPlexShiftPoint_Private(vStart, depth, depthEnd, depthShift), DMPlexShiftPoint_Private(vEnd, depth, depthEnd, depthShift));CHKERRQ(ierr); 3571 for(v = vStart; v < vEnd; ++v) { 3572 const PetscInt newv = DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift); 3573 ierr = PetscSectionSetDof(newCoordSection, newv, dim);CHKERRQ(ierr); 3574 ierr = PetscSectionSetFieldDof(newCoordSection, newv, 0, dim);CHKERRQ(ierr); 3575 } 3576 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3577 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3578 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3579 ierr = DMSetCoordinatesLocal(dmNew, coordinates);CHKERRQ(ierr); 3580 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3581 PetscFunctionReturn(0); 3582 } 3583 3584 #undef __FUNCT__ 3585 #define __FUNCT__ "DMPlexShiftSF_Private" 3586 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3587 { 3588 PetscInt *depthEnd; 3589 PetscInt depth = 0, d; 3590 PetscSF sfPoint, sfPointNew; 3591 const PetscSFNode *remotePoints; 3592 PetscSFNode *gremotePoints; 3593 const PetscInt *localPoints; 3594 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3595 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3596 PetscMPIInt numProcs; 3597 PetscErrorCode ierr; 3598 3599 PetscFunctionBegin; 3600 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3601 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3602 for(d = 0; d <= depth; ++d) { 3603 totShift += depthShift[d]; 3604 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3605 } 3606 /* Step 9: Convert pointSF */ 3607 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3608 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3609 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3610 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3611 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3612 if (numRoots >= 0) { 3613 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3614 for(l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3615 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3616 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3617 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3618 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3619 for(l = 0; l < numLeaves; ++l) { 3620 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3621 gremotePoints[l].rank = remotePoints[l].rank; 3622 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3623 } 3624 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3625 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3626 } 3627 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3628 PetscFunctionReturn(0); 3629 } 3630 3631 #undef __FUNCT__ 3632 #define __FUNCT__ "DMPlexShiftLabels_Private" 3633 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3634 { 3635 PetscSF sfPoint; 3636 DMLabel vtkLabel, ghostLabel; 3637 PetscInt *depthEnd; 3638 const PetscSFNode *leafRemote; 3639 const PetscInt *leafLocal; 3640 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3641 PetscMPIInt rank; 3642 PetscErrorCode ierr; 3643 3644 PetscFunctionBegin; 3645 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3646 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3647 for(d = 0; d <= depth; ++d) { 3648 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3649 } 3650 /* Step 10: Convert labels */ 3651 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3652 for(l = 0; l < numLabels; ++l) { 3653 DMLabel label, newlabel; 3654 const char *lname; 3655 PetscBool isDepth; 3656 IS valueIS; 3657 const PetscInt *values; 3658 PetscInt numValues, val; 3659 3660 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3661 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3662 if (isDepth) continue; 3663 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3664 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3665 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3666 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3667 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3668 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3669 for(val = 0; val < numValues; ++val) { 3670 IS pointIS; 3671 const PetscInt *points; 3672 PetscInt numPoints, p; 3673 3674 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3675 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3676 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3677 for(p = 0; p < numPoints; ++p) { 3678 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3679 3680 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3681 } 3682 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3683 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3684 } 3685 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3686 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3687 } 3688 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3689 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3690 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3691 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3692 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3693 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3694 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3695 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3696 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3697 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3698 for(l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3699 for(; c < leafLocal[l] && c < cEnd; ++c) { 3700 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3701 } 3702 if (leafLocal[l] >= cEnd) break; 3703 if (leafRemote[l].rank == rank) { 3704 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3705 } else { 3706 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3707 } 3708 } 3709 for(; c < cEnd; ++c) { 3710 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3711 } 3712 if (0) { 3713 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3714 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3715 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3716 } 3717 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3718 for(f = fStart; f < fEnd; ++f) { 3719 PetscInt numCells; 3720 3721 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3722 if (numCells < 2) { 3723 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3724 } else { 3725 const PetscInt *cells = PETSC_NULL; 3726 PetscInt vA, vB; 3727 3728 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3729 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3730 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3731 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3732 } 3733 } 3734 if (0) { 3735 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3736 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3737 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3738 } 3739 PetscFunctionReturn(0); 3740 } 3741 3742 #undef __FUNCT__ 3743 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3744 /*@C 3745 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3746 3747 Collective on dm 3748 3749 Input Parameters: 3750 + dm - The original DM 3751 - labelName - The label specifying the boundary faces (this could be auto-generated) 3752 3753 Output Parameters: 3754 + numGhostCells - The number of ghost cells added to the DM 3755 - dmGhosted - The new DM 3756 3757 Level: developer 3758 3759 .seealso: DMCreate() 3760 */ 3761 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3762 { 3763 DMLabel label; 3764 IS valueIS; 3765 const PetscInt *values; 3766 PetscInt *depthShift; 3767 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3768 PetscErrorCode ierr; 3769 3770 PetscFunctionBegin; 3771 /* Count ghost cells */ 3772 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3773 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3774 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3775 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3776 *numGhostCells = 0; 3777 for(fs = 0; fs < numFS; ++fs) { 3778 PetscInt numBdFaces; 3779 3780 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3781 *numGhostCells += numBdFaces; 3782 } 3783 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3784 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3785 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3786 if (depth >= 0) {depthShift[depth] = *numGhostCells;} 3787 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3788 /* Step 3: Set cone/support sizes for new points */ 3789 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3790 for(c = cEnd; c < cEnd + *numGhostCells; ++c) { 3791 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3792 } 3793 for(fs = 0; fs < numFS; ++fs) { 3794 IS faceIS; 3795 const PetscInt *faces; 3796 PetscInt numFaces, f; 3797 3798 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3799 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3800 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3801 for(f = 0; f < numFaces; ++f) { 3802 PetscInt size; 3803 3804 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3805 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3806 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3807 } 3808 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3809 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3810 } 3811 /* Step 4: Setup ghosted DM */ 3812 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3813 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3814 /* Step 6: Set cones and supports for new points */ 3815 ghostCell = cEnd; 3816 for(fs = 0; fs < numFS; ++fs) { 3817 IS faceIS; 3818 const PetscInt *faces; 3819 PetscInt numFaces, f; 3820 3821 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3822 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3823 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3824 for(f = 0; f < numFaces; ++f, ++ghostCell) { 3825 PetscInt newFace = faces[f] + *numGhostCells; 3826 3827 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3828 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3829 } 3830 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3831 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3832 } 3833 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3834 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3835 /* Step 7: Stratify */ 3836 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3837 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3838 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3839 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3840 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3841 PetscFunctionReturn(0); 3842 } 3843 3844 #undef __FUNCT__ 3845 #define __FUNCT__ "DMPlexConstructGhostCells" 3846 /*@C 3847 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3848 3849 Collective on dm 3850 3851 Input Parameters: 3852 + dm - The original DM 3853 - labelName - The label specifying the boundary faces (this could be auto-generated) 3854 3855 Output Parameters: 3856 + numGhostCells - The number of ghost cells added to the DM 3857 - dmGhosted - The new DM 3858 3859 Level: developer 3860 3861 .seealso: DMCreate() 3862 */ 3863 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3864 { 3865 DM gdm; 3866 PetscInt dim; 3867 PetscErrorCode ierr; 3868 3869 PetscFunctionBegin; 3870 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3871 PetscValidPointer(numGhostCells, 3); 3872 PetscValidPointer(dmGhosted, 4); 3873 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3874 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3875 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3876 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3877 switch(dim) { 3878 case 2: 3879 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3880 break; 3881 default: 3882 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3883 } 3884 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3885 *dmGhosted = gdm; 3886 PetscFunctionReturn(0); 3887 } 3888 3889 #undef __FUNCT__ 3890 #define __FUNCT__ "DMPlexInterpolate_2D" 3891 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 3892 { 3893 DM idm; 3894 DM_Plex *mesh; 3895 PetscHashIJ edgeTable; 3896 PetscInt *off; 3897 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 3898 PetscInt numEdges, firstEdge, edge, e; 3899 PetscErrorCode ierr; 3900 3901 PetscFunctionBegin; 3902 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3903 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3904 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3905 numCells = cEnd - cStart; 3906 numVertices = vEnd - vStart; 3907 firstEdge = numCells + numVertices; 3908 numEdges = 0 ; 3909 /* Count edges using algorithm from CreateNeighborCSR */ 3910 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 3911 if (off) { 3912 PetscInt numCorners = 0; 3913 3914 numEdges = off[numCells]/2; 3915 #if 0 3916 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 3917 numEdges += 3*numCells - off[numCells]; 3918 #else 3919 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 3920 for(c = cStart; c < cEnd; ++c) { 3921 PetscInt coneSize; 3922 3923 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 3924 numCorners += coneSize; 3925 } 3926 numEdges += numCorners - off[numCells]; 3927 #endif 3928 } 3929 #if 0 3930 /* Check Euler characteristic V - E + F = 1 */ 3931 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 3932 #endif 3933 /* Create interpolated mesh */ 3934 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 3935 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 3936 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 3937 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 3938 for (c = 0; c < numCells; ++c) { 3939 PetscInt numCorners; 3940 3941 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 3942 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 3943 } 3944 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 3945 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 3946 } 3947 ierr = DMSetUp(idm);CHKERRQ(ierr); 3948 /* Get edge cones from subsets of cell vertices */ 3949 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 3950 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 3951 3952 for (c = 0, edge = firstEdge; c < numCells; ++c) { 3953 const PetscInt *cellFaces; 3954 PetscInt numCellFaces, faceSize, cf; 3955 3956 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 3957 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 3958 for (cf = 0; cf < numCellFaces; ++cf) { 3959 #if 1 3960 PetscHashIJKey key = {PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]), 3961 PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1])}; 3962 3963 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 3964 if (e < 0) { 3965 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3966 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 3967 e = edge++; 3968 } 3969 #else 3970 PetscBool found = PETSC_FALSE; 3971 3972 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 3973 for (e = firstEdge; e < edge; ++e) { 3974 const PetscInt *cone; 3975 3976 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 3977 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 3978 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 3979 found = PETSC_TRUE; 3980 break; 3981 } 3982 } 3983 if (!found) { 3984 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3985 ++edge; 3986 } 3987 #endif 3988 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 3989 } 3990 } 3991 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 3992 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 3993 ierr = PetscFree(off);CHKERRQ(ierr); 3994 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 3995 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 3996 mesh = (DM_Plex *) (idm)->data; 3997 /* Orient edges */ 3998 for (c = 0; c < numCells; ++c) { 3999 const PetscInt *cone = PETSC_NULL, *cellFaces; 4000 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4001 4002 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4003 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4004 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4005 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4006 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4007 for (cf = 0; cf < numCellFaces; ++cf) { 4008 const PetscInt *econe = PETSC_NULL; 4009 PetscInt esize; 4010 4011 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4012 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4013 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]); 4014 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4015 /* Correctly oriented */ 4016 mesh->coneOrientations[coff+cf] = 0; 4017 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4018 /* Start at index 1, and reverse orientation */ 4019 mesh->coneOrientations[coff+cf] = -(1+1); 4020 } 4021 } 4022 } 4023 *dmInt = idm; 4024 PetscFunctionReturn(0); 4025 } 4026 4027 #undef __FUNCT__ 4028 #define __FUNCT__ "DMPlexInterpolate_3D" 4029 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4030 { 4031 DM idm, fdm; 4032 DM_Plex *mesh; 4033 PetscInt *off; 4034 const PetscInt numCorners = 4; 4035 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4036 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4037 PetscErrorCode ierr; 4038 4039 PetscFunctionBegin; 4040 { 4041 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4042 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4043 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4044 } 4045 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4046 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4047 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4048 numCells = cEnd - cStart; 4049 numVertices = vEnd - vStart; 4050 firstFace = numCells + numVertices; 4051 numFaces = 0 ; 4052 /* Count faces using algorithm from CreateNeighborCSR */ 4053 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4054 if (off) { 4055 numFaces = off[numCells]/2; 4056 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4057 numFaces += 4*numCells - off[numCells]; 4058 } 4059 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4060 firstEdge = firstFace + numFaces; 4061 numEdges = numVertices + numFaces - numCells - 1; 4062 /* Create interpolated mesh */ 4063 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4064 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4065 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4066 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4067 for (c = 0; c < numCells; ++c) { 4068 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4069 } 4070 for (f = firstFace; f < firstFace+numFaces; ++f) { 4071 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4072 } 4073 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4074 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4075 } 4076 ierr = DMSetUp(idm);CHKERRQ(ierr); 4077 /* Get face cones from subsets of cell vertices */ 4078 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4079 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4080 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4081 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4082 for (f = firstFace; f < firstFace+numFaces; ++f) { 4083 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4084 } 4085 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4086 for (c = 0, face = firstFace; c < numCells; ++c) { 4087 const PetscInt *cellFaces; 4088 PetscInt numCellFaces, faceSize, cf; 4089 4090 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4091 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4092 for (cf = 0; cf < numCellFaces; ++cf) { 4093 PetscBool found = PETSC_FALSE; 4094 4095 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4096 for (f = firstFace; f < face; ++f) { 4097 const PetscInt *cone = PETSC_NULL; 4098 4099 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4100 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4101 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4102 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4103 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4104 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4105 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4106 found = PETSC_TRUE; 4107 break; 4108 } 4109 } 4110 if (!found) { 4111 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4112 /* Save the vertices for orientation calculation */ 4113 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4114 ++face; 4115 } 4116 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4117 } 4118 } 4119 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4120 /* Get edge cones from subsets of face vertices */ 4121 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4122 const PetscInt *cellFaces; 4123 PetscInt numCellFaces, faceSize, cf; 4124 4125 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4126 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4127 for (cf = 0; cf < numCellFaces; ++cf) { 4128 PetscBool found = PETSC_FALSE; 4129 4130 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4131 for (e = firstEdge; e < edge; ++e) { 4132 const PetscInt *cone = PETSC_NULL; 4133 4134 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4135 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4136 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4137 found = PETSC_TRUE; 4138 break; 4139 } 4140 } 4141 if (!found) { 4142 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4143 ++edge; 4144 } 4145 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4146 } 4147 } 4148 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4149 ierr = PetscFree(off);CHKERRQ(ierr); 4150 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4151 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4152 mesh = (DM_Plex *) (idm)->data; 4153 /* Orient edges */ 4154 for (f = firstFace; f < firstFace+numFaces; ++f) { 4155 const PetscInt *cone, *cellFaces; 4156 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4157 4158 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4159 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4160 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4161 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4162 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4163 for (cf = 0; cf < numCellFaces; ++cf) { 4164 const PetscInt *econe; 4165 PetscInt esize; 4166 4167 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4168 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4169 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]); 4170 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4171 /* Correctly oriented */ 4172 mesh->coneOrientations[coff+cf] = 0; 4173 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4174 /* Start at index 1, and reverse orientation */ 4175 mesh->coneOrientations[coff+cf] = -(1+1); 4176 } 4177 } 4178 } 4179 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4180 /* Orient faces */ 4181 for (c = 0; c < numCells; ++c) { 4182 const PetscInt *cone, *cellFaces; 4183 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4184 4185 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4186 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4187 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4188 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4189 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4190 for (cf = 0; cf < numCellFaces; ++cf) { 4191 PetscInt *origClosure = PETSC_NULL, *closure; 4192 PetscInt closureSize, i; 4193 4194 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4195 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4196 for (i = 4; i < 7; ++i) { 4197 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); 4198 } 4199 closure = &origClosure[4*2]; 4200 /* Remember that this is the orientation for edges, not vertices */ 4201 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4202 /* Correctly oriented */ 4203 mesh->coneOrientations[coff+cf] = 0; 4204 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4205 /* Shifted by 1 */ 4206 mesh->coneOrientations[coff+cf] = 1; 4207 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4208 /* Shifted by 2 */ 4209 mesh->coneOrientations[coff+cf] = 2; 4210 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4211 /* Start at edge 1, and reverse orientation */ 4212 mesh->coneOrientations[coff+cf] = -(1+1); 4213 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4214 /* Start at index 0, and reverse orientation */ 4215 mesh->coneOrientations[coff+cf] = -(0+1); 4216 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4217 /* Start at index 2, and reverse orientation */ 4218 mesh->coneOrientations[coff+cf] = -(2+1); 4219 } 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); 4220 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4221 } 4222 } 4223 { 4224 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4225 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4226 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4227 } 4228 *dmInt = idm; 4229 PetscFunctionReturn(0); 4230 } 4231 4232 #undef __FUNCT__ 4233 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4234 /* 4235 This takes as input the common mesh generator output, a list of the vertices for each cell 4236 */ 4237 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4238 { 4239 PetscInt *cone, c, p; 4240 PetscErrorCode ierr; 4241 4242 PetscFunctionBegin; 4243 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4244 for (c = 0; c < numCells; ++c) { 4245 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4246 } 4247 ierr = DMSetUp(dm);CHKERRQ(ierr); 4248 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4249 for (c = 0; c < numCells; ++c) { 4250 for (p = 0; p < numCorners; ++p) { 4251 cone[p] = cells[c*numCorners+p]+numCells; 4252 } 4253 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4254 } 4255 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4256 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4257 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4258 PetscFunctionReturn(0); 4259 } 4260 4261 #undef __FUNCT__ 4262 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4263 /* 4264 This takes as input the coordinates for each vertex 4265 */ 4266 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4267 { 4268 PetscSection coordSection; 4269 Vec coordinates; 4270 PetscScalar *coords; 4271 PetscInt coordSize, v, d; 4272 PetscErrorCode ierr; 4273 4274 PetscFunctionBegin; 4275 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4276 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4277 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4278 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4279 for (v = numCells; v < numCells+numVertices; ++v) { 4280 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4281 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4282 } 4283 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4284 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4285 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4286 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4287 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4288 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4289 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4290 for (v = 0; v < numVertices; ++v) { 4291 for (d = 0; d < spaceDim; ++d) { 4292 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4293 } 4294 } 4295 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4296 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4297 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4298 PetscFunctionReturn(0); 4299 } 4300 4301 #undef __FUNCT__ 4302 #define __FUNCT__ "DMPlexCreateFromCellList" 4303 /* 4304 This takes as input the common mesh generator output, a list of the vertices for each cell 4305 */ 4306 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4307 { 4308 PetscErrorCode ierr; 4309 4310 PetscFunctionBegin; 4311 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4312 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4313 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4314 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4315 if (interpolate) { 4316 DM idm; 4317 4318 switch(dim) { 4319 case 2: 4320 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4321 case 3: 4322 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4323 default: 4324 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4325 } 4326 ierr = DMDestroy(dm);CHKERRQ(ierr); 4327 *dm = idm; 4328 } 4329 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4330 PetscFunctionReturn(0); 4331 } 4332 4333 #ifdef PETSC_HAVE_TRIANGLE 4334 #include <triangle.h> 4335 4336 #undef __FUNCT__ 4337 #define __FUNCT__ "InitInput_Triangle" 4338 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) { 4339 PetscFunctionBegin; 4340 inputCtx->numberofpoints = 0; 4341 inputCtx->numberofpointattributes = 0; 4342 inputCtx->pointlist = PETSC_NULL; 4343 inputCtx->pointattributelist = PETSC_NULL; 4344 inputCtx->pointmarkerlist = PETSC_NULL; 4345 inputCtx->numberofsegments = 0; 4346 inputCtx->segmentlist = PETSC_NULL; 4347 inputCtx->segmentmarkerlist = PETSC_NULL; 4348 inputCtx->numberoftriangleattributes = 0; 4349 inputCtx->trianglelist = PETSC_NULL; 4350 inputCtx->numberofholes = 0; 4351 inputCtx->holelist = PETSC_NULL; 4352 inputCtx->numberofregions = 0; 4353 inputCtx->regionlist = PETSC_NULL; 4354 PetscFunctionReturn(0); 4355 } 4356 4357 #undef __FUNCT__ 4358 #define __FUNCT__ "InitOutput_Triangle" 4359 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) { 4360 PetscFunctionBegin; 4361 outputCtx->numberofpoints = 0; 4362 outputCtx->pointlist = PETSC_NULL; 4363 outputCtx->pointattributelist = PETSC_NULL; 4364 outputCtx->pointmarkerlist = PETSC_NULL; 4365 outputCtx->numberoftriangles = 0; 4366 outputCtx->trianglelist = PETSC_NULL; 4367 outputCtx->triangleattributelist = PETSC_NULL; 4368 outputCtx->neighborlist = PETSC_NULL; 4369 outputCtx->segmentlist = PETSC_NULL; 4370 outputCtx->segmentmarkerlist = PETSC_NULL; 4371 outputCtx->numberofedges = 0; 4372 outputCtx->edgelist = PETSC_NULL; 4373 outputCtx->edgemarkerlist = PETSC_NULL; 4374 PetscFunctionReturn(0); 4375 } 4376 4377 #undef __FUNCT__ 4378 #define __FUNCT__ "FiniOutput_Triangle" 4379 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) { 4380 PetscFunctionBegin; 4381 free(outputCtx->pointmarkerlist); 4382 free(outputCtx->edgelist); 4383 free(outputCtx->edgemarkerlist); 4384 free(outputCtx->trianglelist); 4385 free(outputCtx->neighborlist); 4386 PetscFunctionReturn(0); 4387 } 4388 4389 #undef __FUNCT__ 4390 #define __FUNCT__ "DMPlexGenerate_Triangle" 4391 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4392 { 4393 MPI_Comm comm = ((PetscObject) boundary)->comm; 4394 PetscInt dim = 2; 4395 const PetscBool createConvexHull = PETSC_FALSE; 4396 const PetscBool constrained = PETSC_FALSE; 4397 struct triangulateio in; 4398 struct triangulateio out; 4399 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4400 PetscMPIInt rank; 4401 PetscErrorCode ierr; 4402 4403 PetscFunctionBegin; 4404 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4405 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4406 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4407 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4408 in.numberofpoints = vEnd - vStart; 4409 if (in.numberofpoints > 0) { 4410 PetscSection coordSection; 4411 Vec coordinates; 4412 PetscScalar *array; 4413 4414 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4415 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4416 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4417 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4418 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4419 for (v = vStart; v < vEnd; ++v) { 4420 const PetscInt idx = v - vStart; 4421 PetscInt off, d; 4422 4423 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4424 for (d = 0; d < dim; ++d) { 4425 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4426 } 4427 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4428 } 4429 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4430 } 4431 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4432 in.numberofsegments = eEnd - eStart; 4433 if (in.numberofsegments > 0) { 4434 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4435 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4436 for (e = eStart; e < eEnd; ++e) { 4437 const PetscInt idx = e - eStart; 4438 const PetscInt *cone; 4439 4440 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4441 in.segmentlist[idx*2+0] = cone[0] - vStart; 4442 in.segmentlist[idx*2+1] = cone[1] - vStart; 4443 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4444 } 4445 } 4446 #if 0 /* Do not currently support holes */ 4447 PetscReal *holeCoords; 4448 PetscInt h, d; 4449 4450 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4451 if (in.numberofholes > 0) { 4452 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4453 for (h = 0; h < in.numberofholes; ++h) { 4454 for (d = 0; d < dim; ++d) { 4455 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4456 } 4457 } 4458 } 4459 #endif 4460 if (!rank) { 4461 char args[32]; 4462 4463 /* Take away 'Q' for verbose output */ 4464 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4465 if (createConvexHull) { 4466 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4467 } 4468 if (constrained) { 4469 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4470 } 4471 triangulate(args, &in, &out, PETSC_NULL); 4472 } 4473 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4474 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4475 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4476 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4477 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4478 4479 { 4480 const PetscInt numCorners = 3; 4481 const PetscInt numCells = out.numberoftriangles; 4482 const PetscInt numVertices = out.numberofpoints; 4483 const int *cells = out.trianglelist; 4484 const double *meshCoords = out.pointlist; 4485 4486 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4487 /* Set labels */ 4488 for (v = 0; v < numVertices; ++v) { 4489 if (out.pointmarkerlist[v]) { 4490 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4491 } 4492 } 4493 if (interpolate) { 4494 for (e = 0; e < out.numberofedges; e++) { 4495 if (out.edgemarkerlist[e]) { 4496 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4497 const PetscInt *edges; 4498 PetscInt numEdges; 4499 4500 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4501 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4502 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4503 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4504 } 4505 } 4506 } 4507 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4508 } 4509 #if 0 /* Do not currently support holes */ 4510 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4511 #endif 4512 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4513 PetscFunctionReturn(0); 4514 } 4515 4516 #undef __FUNCT__ 4517 #define __FUNCT__ "DMPlexRefine_Triangle" 4518 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4519 { 4520 MPI_Comm comm = ((PetscObject) dm)->comm; 4521 PetscInt dim = 2; 4522 struct triangulateio in; 4523 struct triangulateio out; 4524 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4525 PetscMPIInt rank; 4526 PetscErrorCode ierr; 4527 4528 PetscFunctionBegin; 4529 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4530 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4531 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4532 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4533 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4534 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4535 in.numberofpoints = vEnd - vStart; 4536 if (in.numberofpoints > 0) { 4537 PetscSection coordSection; 4538 Vec coordinates; 4539 PetscScalar *array; 4540 4541 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4542 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4543 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4544 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4545 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4546 for (v = vStart; v < vEnd; ++v) { 4547 const PetscInt idx = v - vStart; 4548 PetscInt off, d; 4549 4550 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4551 for (d = 0; d < dim; ++d) { 4552 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4553 } 4554 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4555 } 4556 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4557 } 4558 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4559 in.numberofcorners = 3; 4560 in.numberoftriangles = cEnd - cStart; 4561 in.trianglearealist = (double *) maxVolumes; 4562 if (in.numberoftriangles > 0) { 4563 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4564 for (c = cStart; c < cEnd; ++c) { 4565 const PetscInt idx = c - cStart; 4566 PetscInt *closure = PETSC_NULL; 4567 PetscInt closureSize; 4568 4569 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4570 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4571 for (v = 0; v < 3; ++v) { 4572 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4573 } 4574 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4575 } 4576 } 4577 /* TODO: Segment markers are missing on input */ 4578 #if 0 /* Do not currently support holes */ 4579 PetscReal *holeCoords; 4580 PetscInt h, d; 4581 4582 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4583 if (in.numberofholes > 0) { 4584 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4585 for (h = 0; h < in.numberofholes; ++h) { 4586 for (d = 0; d < dim; ++d) { 4587 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4588 } 4589 } 4590 } 4591 #endif 4592 if (!rank) { 4593 char args[32]; 4594 4595 /* Take away 'Q' for verbose output */ 4596 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4597 triangulate(args, &in, &out, PETSC_NULL); 4598 } 4599 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4600 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4601 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4602 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4603 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4604 4605 { 4606 const PetscInt numCorners = 3; 4607 const PetscInt numCells = out.numberoftriangles; 4608 const PetscInt numVertices = out.numberofpoints; 4609 const int *cells = out.trianglelist; 4610 const double *meshCoords = out.pointlist; 4611 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4612 4613 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4614 /* Set labels */ 4615 for (v = 0; v < numVertices; ++v) { 4616 if (out.pointmarkerlist[v]) { 4617 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4618 } 4619 } 4620 if (interpolate) { 4621 PetscInt e; 4622 4623 for (e = 0; e < out.numberofedges; e++) { 4624 if (out.edgemarkerlist[e]) { 4625 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4626 const PetscInt *edges; 4627 PetscInt numEdges; 4628 4629 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4630 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4631 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4632 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4633 } 4634 } 4635 } 4636 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4637 } 4638 #if 0 /* Do not currently support holes */ 4639 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4640 #endif 4641 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4642 PetscFunctionReturn(0); 4643 } 4644 #endif 4645 4646 #ifdef PETSC_HAVE_TETGEN 4647 #include <tetgen.h> 4648 #undef __FUNCT__ 4649 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4650 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4651 { 4652 MPI_Comm comm = ((PetscObject) boundary)->comm; 4653 const PetscInt dim = 3; 4654 ::tetgenio in; 4655 ::tetgenio out; 4656 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4657 PetscMPIInt rank; 4658 PetscErrorCode ierr; 4659 4660 PetscFunctionBegin; 4661 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4662 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4663 in.numberofpoints = vEnd - vStart; 4664 if (in.numberofpoints > 0) { 4665 PetscSection coordSection; 4666 Vec coordinates; 4667 PetscScalar *array; 4668 4669 in.pointlist = new double[in.numberofpoints*dim]; 4670 in.pointmarkerlist = new int[in.numberofpoints]; 4671 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4672 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4673 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4674 for (v = vStart; v < vEnd; ++v) { 4675 const PetscInt idx = v - vStart; 4676 PetscInt off, d; 4677 4678 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4679 for (d = 0; d < dim; ++d) { 4680 in.pointlist[idx*dim + d] = array[off+d]; 4681 } 4682 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4683 } 4684 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4685 } 4686 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4687 in.numberoffacets = fEnd - fStart; 4688 if (in.numberoffacets > 0) { 4689 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4690 in.facetmarkerlist = new int[in.numberoffacets]; 4691 for (f = fStart; f < fEnd; ++f) { 4692 const PetscInt idx = f - fStart; 4693 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 4694 4695 in.facetlist[idx].numberofpolygons = 1; 4696 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4697 in.facetlist[idx].numberofholes = 0; 4698 in.facetlist[idx].holelist = NULL; 4699 4700 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4701 for (p = 0; p < numPoints*2; p += 2) { 4702 const PetscInt point = points[p]; 4703 if ((point >= vStart) && (point < vEnd)) { 4704 points[numVertices++] = point; 4705 } 4706 } 4707 4708 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4709 poly->numberofvertices = numVertices; 4710 poly->vertexlist = new int[poly->numberofvertices]; 4711 for (v = 0; v < numVertices; ++v) { 4712 const PetscInt vIdx = points[v] - vStart; 4713 poly->vertexlist[v] = vIdx; 4714 } 4715 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4716 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4717 } 4718 } 4719 if (!rank) { 4720 char args[32]; 4721 4722 /* Take away 'Q' for verbose output */ 4723 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4724 ::tetrahedralize(args, &in, &out); 4725 } 4726 { 4727 const PetscInt numCorners = 4; 4728 const PetscInt numCells = out.numberoftetrahedra; 4729 const PetscInt numVertices = out.numberofpoints; 4730 const int *cells = out.tetrahedronlist; 4731 const double *meshCoords = out.pointlist; 4732 4733 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4734 /* Set labels */ 4735 for (v = 0; v < numVertices; ++v) { 4736 if (out.pointmarkerlist[v]) { 4737 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4738 } 4739 } 4740 if (interpolate) { 4741 PetscInt e; 4742 4743 for (e = 0; e < out.numberofedges; e++) { 4744 if (out.edgemarkerlist[e]) { 4745 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4746 const PetscInt *edges; 4747 PetscInt numEdges; 4748 4749 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4750 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4751 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4752 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4753 } 4754 } 4755 for (f = 0; f < out.numberoftrifaces; f++) { 4756 if (out.trifacemarkerlist[f]) { 4757 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4758 const PetscInt *faces; 4759 PetscInt numFaces; 4760 4761 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4762 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4763 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4764 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4765 } 4766 } 4767 } 4768 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4769 } 4770 PetscFunctionReturn(0); 4771 } 4772 4773 #undef __FUNCT__ 4774 #define __FUNCT__ "DMPlexRefine_Tetgen" 4775 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4776 { 4777 MPI_Comm comm = ((PetscObject) dm)->comm; 4778 const PetscInt dim = 3; 4779 ::tetgenio in; 4780 ::tetgenio out; 4781 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4782 PetscMPIInt rank; 4783 PetscErrorCode ierr; 4784 4785 PetscFunctionBegin; 4786 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4787 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4788 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4789 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4790 in.numberofpoints = vEnd - vStart; 4791 if (in.numberofpoints > 0) { 4792 PetscSection coordSection; 4793 Vec coordinates; 4794 PetscScalar *array; 4795 4796 in.pointlist = new double[in.numberofpoints*dim]; 4797 in.pointmarkerlist = new int[in.numberofpoints]; 4798 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4799 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4800 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4801 for (v = vStart; v < vEnd; ++v) { 4802 const PetscInt idx = v - vStart; 4803 PetscInt off, d; 4804 4805 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4806 for (d = 0; d < dim; ++d) { 4807 in.pointlist[idx*dim + d] = array[off+d]; 4808 } 4809 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4810 } 4811 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4812 } 4813 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4814 in.numberofcorners = 4; 4815 in.numberoftetrahedra = cEnd - cStart; 4816 in.tetrahedronvolumelist = (double *) maxVolumes; 4817 if (in.numberoftetrahedra > 0) { 4818 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 4819 for (c = cStart; c < cEnd; ++c) { 4820 const PetscInt idx = c - cStart; 4821 PetscInt *closure = PETSC_NULL; 4822 PetscInt closureSize; 4823 4824 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4825 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 4826 for (v = 0; v < 4; ++v) { 4827 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 4828 } 4829 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4830 } 4831 } 4832 /* TODO: Put in boundary faces with markers */ 4833 if (!rank) { 4834 char args[32]; 4835 4836 /* Take away 'Q' for verbose output */ 4837 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 4838 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 4839 ::tetrahedralize(args, &in, &out); 4840 } 4841 in.tetrahedronvolumelist = NULL; 4842 4843 { 4844 const PetscInt numCorners = 4; 4845 const PetscInt numCells = out.numberoftetrahedra; 4846 const PetscInt numVertices = out.numberofpoints; 4847 const int *cells = out.tetrahedronlist; 4848 const double *meshCoords = out.pointlist; 4849 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4850 4851 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4852 /* Set labels */ 4853 for (v = 0; v < numVertices; ++v) { 4854 if (out.pointmarkerlist[v]) { 4855 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4856 } 4857 } 4858 if (interpolate) { 4859 PetscInt e, f; 4860 4861 for (e = 0; e < out.numberofedges; e++) { 4862 if (out.edgemarkerlist[e]) { 4863 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4864 const PetscInt *edges; 4865 PetscInt numEdges; 4866 4867 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4868 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4869 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4870 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4871 } 4872 } 4873 for (f = 0; f < out.numberoftrifaces; f++) { 4874 if (out.trifacemarkerlist[f]) { 4875 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4876 const PetscInt *faces; 4877 PetscInt numFaces; 4878 4879 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4880 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4881 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4882 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4883 } 4884 } 4885 } 4886 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4887 } 4888 PetscFunctionReturn(0); 4889 } 4890 #endif 4891 4892 #ifdef PETSC_HAVE_CTETGEN 4893 #include "ctetgen.h" 4894 4895 #undef __FUNCT__ 4896 #define __FUNCT__ "DMPlexGenerate_CTetgen" 4897 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 4898 { 4899 MPI_Comm comm = ((PetscObject) boundary)->comm; 4900 const PetscInt dim = 3; 4901 PLC *in, *out; 4902 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 4903 PetscMPIInt rank; 4904 PetscErrorCode ierr; 4905 4906 PetscFunctionBegin; 4907 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 4908 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4909 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4910 ierr = PLCCreate(&in);CHKERRQ(ierr); 4911 ierr = PLCCreate(&out);CHKERRQ(ierr); 4912 in->numberofpoints = vEnd - vStart; 4913 if (in->numberofpoints > 0) { 4914 PetscSection coordSection; 4915 Vec coordinates; 4916 PetscScalar *array; 4917 4918 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 4919 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 4920 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4921 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4922 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4923 for (v = vStart; v < vEnd; ++v) { 4924 const PetscInt idx = v - vStart; 4925 PetscInt off, d, m; 4926 4927 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4928 for (d = 0; d < dim; ++d) { 4929 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4930 } 4931 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 4932 in->pointmarkerlist[idx] = (int) m; 4933 } 4934 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4935 } 4936 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4937 in->numberoffacets = fEnd - fStart; 4938 if (in->numberoffacets > 0) { 4939 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 4940 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 4941 for (f = fStart; f < fEnd; ++f) { 4942 const PetscInt idx = f - fStart; 4943 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 4944 polygon *poly; 4945 4946 in->facetlist[idx].numberofpolygons = 1; 4947 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 4948 in->facetlist[idx].numberofholes = 0; 4949 in->facetlist[idx].holelist = PETSC_NULL; 4950 4951 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4952 for (p = 0; p < numPoints*2; p += 2) { 4953 const PetscInt point = points[p]; 4954 if ((point >= vStart) && (point < vEnd)) { 4955 points[numVertices++] = point; 4956 } 4957 } 4958 4959 poly = in->facetlist[idx].polygonlist; 4960 poly->numberofvertices = numVertices; 4961 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 4962 for (v = 0; v < numVertices; ++v) { 4963 const PetscInt vIdx = points[v] - vStart; 4964 poly->vertexlist[v] = vIdx; 4965 } 4966 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 4967 in->facetmarkerlist[idx] = (int) m; 4968 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4969 } 4970 } 4971 if (!rank) { 4972 TetGenOpts t; 4973 4974 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 4975 t.in = boundary; /* Should go away */ 4976 t.plc = 1; 4977 t.quality = 1; 4978 t.edgesout = 1; 4979 t.zeroindex = 1; 4980 t.quiet = 1; 4981 t.verbose = verbose; 4982 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 4983 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 4984 } 4985 { 4986 const PetscInt numCorners = 4; 4987 const PetscInt numCells = out->numberoftetrahedra; 4988 const PetscInt numVertices = out->numberofpoints; 4989 const int *cells = out->tetrahedronlist; 4990 const double *meshCoords = out->pointlist; 4991 4992 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4993 /* Set labels */ 4994 for (v = 0; v < numVertices; ++v) { 4995 if (out->pointmarkerlist[v]) { 4996 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 4997 } 4998 } 4999 if (interpolate) { 5000 PetscInt e; 5001 5002 for (e = 0; e < out->numberofedges; e++) { 5003 if (out->edgemarkerlist[e]) { 5004 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5005 const PetscInt *edges; 5006 PetscInt numEdges; 5007 5008 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5009 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5010 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5011 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5012 } 5013 } 5014 for (f = 0; f < out->numberoftrifaces; f++) { 5015 if (out->trifacemarkerlist[f]) { 5016 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5017 const PetscInt *faces; 5018 PetscInt numFaces; 5019 5020 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5021 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5022 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5023 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5024 } 5025 } 5026 } 5027 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5028 } 5029 5030 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5031 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5032 PetscFunctionReturn(0); 5033 } 5034 5035 #undef __FUNCT__ 5036 #define __FUNCT__ "DMPlexRefine_CTetgen" 5037 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5038 { 5039 MPI_Comm comm = ((PetscObject) dm)->comm; 5040 const PetscInt dim = 3; 5041 PLC *in, *out; 5042 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5043 PetscMPIInt rank; 5044 PetscErrorCode ierr; 5045 5046 PetscFunctionBegin; 5047 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5048 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5049 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5050 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5051 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5052 ierr = PLCCreate(&in);CHKERRQ(ierr); 5053 ierr = PLCCreate(&out);CHKERRQ(ierr); 5054 in->numberofpoints = vEnd - vStart; 5055 if (in->numberofpoints > 0) { 5056 PetscSection coordSection; 5057 Vec coordinates; 5058 PetscScalar *array; 5059 5060 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5061 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5062 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5063 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5064 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5065 for (v = vStart; v < vEnd; ++v) { 5066 const PetscInt idx = v - vStart; 5067 PetscInt off, d, m; 5068 5069 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5070 for (d = 0; d < dim; ++d) { 5071 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5072 } 5073 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5074 in->pointmarkerlist[idx] = (int) m; 5075 } 5076 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5077 } 5078 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5079 in->numberofcorners = 4; 5080 in->numberoftetrahedra = cEnd - cStart; 5081 in->tetrahedronvolumelist = maxVolumes; 5082 if (in->numberoftetrahedra > 0) { 5083 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5084 for (c = cStart; c < cEnd; ++c) { 5085 const PetscInt idx = c - cStart; 5086 PetscInt *closure = PETSC_NULL; 5087 PetscInt closureSize; 5088 5089 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5090 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5091 for (v = 0; v < 4; ++v) { 5092 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5093 } 5094 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5095 } 5096 } 5097 if (!rank) { 5098 TetGenOpts t; 5099 5100 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5101 t.in = dm; /* Should go away */ 5102 t.refine = 1; 5103 t.varvolume = 1; 5104 t.quality = 1; 5105 t.edgesout = 1; 5106 t.zeroindex = 1; 5107 t.quiet = 1; 5108 t.verbose = verbose; /* Change this */ 5109 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5110 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5111 } 5112 { 5113 const PetscInt numCorners = 4; 5114 const PetscInt numCells = out->numberoftetrahedra; 5115 const PetscInt numVertices = out->numberofpoints; 5116 const int *cells = out->tetrahedronlist; 5117 const double *meshCoords = out->pointlist; 5118 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5119 5120 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5121 /* Set labels */ 5122 for (v = 0; v < numVertices; ++v) { 5123 if (out->pointmarkerlist[v]) { 5124 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5125 } 5126 } 5127 if (interpolate) { 5128 PetscInt e, f; 5129 5130 for (e = 0; e < out->numberofedges; e++) { 5131 if (out->edgemarkerlist[e]) { 5132 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5133 const PetscInt *edges; 5134 PetscInt numEdges; 5135 5136 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5137 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5138 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5139 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5140 } 5141 } 5142 for (f = 0; f < out->numberoftrifaces; f++) { 5143 if (out->trifacemarkerlist[f]) { 5144 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5145 const PetscInt *faces; 5146 PetscInt numFaces; 5147 5148 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5149 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5150 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5151 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5152 } 5153 } 5154 } 5155 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5156 } 5157 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5158 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5159 PetscFunctionReturn(0); 5160 } 5161 #endif 5162 5163 #undef __FUNCT__ 5164 #define __FUNCT__ "DMPlexGenerate" 5165 /*@C 5166 DMPlexGenerate - Generates a mesh. 5167 5168 Not Collective 5169 5170 Input Parameters: 5171 + boundary - The DMPlex boundary object 5172 . name - The mesh generation package name 5173 - interpolate - Flag to create intermediate mesh elements 5174 5175 Output Parameter: 5176 . mesh - The DMPlex object 5177 5178 Level: intermediate 5179 5180 .keywords: mesh, elements 5181 .seealso: DMPlexCreate(), DMRefine() 5182 @*/ 5183 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5184 { 5185 PetscInt dim; 5186 char genname[1024]; 5187 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5188 PetscErrorCode ierr; 5189 5190 PetscFunctionBegin; 5191 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5192 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5193 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5194 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5195 if (flg) {name = genname;} 5196 if (name) { 5197 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5198 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5199 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5200 } 5201 switch(dim) { 5202 case 1: 5203 if (!name || isTriangle) { 5204 #ifdef PETSC_HAVE_TRIANGLE 5205 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5206 #else 5207 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5208 #endif 5209 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5210 break; 5211 case 2: 5212 if (!name || isCTetgen) { 5213 #ifdef PETSC_HAVE_CTETGEN 5214 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5215 #else 5216 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5217 #endif 5218 } else if (isTetgen) { 5219 #ifdef PETSC_HAVE_TETGEN 5220 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5221 #else 5222 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5223 #endif 5224 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5225 break; 5226 default: 5227 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5228 } 5229 PetscFunctionReturn(0); 5230 } 5231 5232 typedef PetscInt CellRefiner; 5233 5234 #undef __FUNCT__ 5235 #define __FUNCT__ "GetDepthStart_Private" 5236 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5237 { 5238 PetscFunctionBegin; 5239 if (cStart) *cStart = 0; 5240 if (vStart) *vStart = depthSize[depth]; 5241 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5242 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5243 PetscFunctionReturn(0); 5244 } 5245 5246 #undef __FUNCT__ 5247 #define __FUNCT__ "GetDepthEnd_Private" 5248 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5249 { 5250 PetscFunctionBegin; 5251 if (cEnd) *cEnd = depthSize[depth]; 5252 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5253 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5254 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5255 PetscFunctionReturn(0); 5256 } 5257 5258 #undef __FUNCT__ 5259 #define __FUNCT__ "CellRefinerGetSizes" 5260 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5261 { 5262 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5263 PetscErrorCode ierr; 5264 5265 PetscFunctionBegin; 5266 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5267 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5268 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5269 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5270 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5271 switch(refiner) { 5272 case 1: 5273 /* Simplicial 2D */ 5274 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5275 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5276 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5277 break; 5278 case 3: 5279 /* Hybrid 2D */ 5280 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5281 cMax = PetscMin(cEnd, cMax); 5282 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5283 fMax = PetscMin(fEnd, fMax); 5284 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5285 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 */ 5286 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5287 break; 5288 case 2: 5289 /* Hex 2D */ 5290 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5291 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5292 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5293 break; 5294 default: 5295 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5296 } 5297 PetscFunctionReturn(0); 5298 } 5299 5300 #undef __FUNCT__ 5301 #define __FUNCT__ "CellRefinerSetConeSizes" 5302 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5303 { 5304 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5305 PetscErrorCode ierr; 5306 5307 PetscFunctionBegin; 5308 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5309 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5310 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5311 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5312 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5313 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5314 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5315 switch(refiner) { 5316 case 1: 5317 /* Simplicial 2D */ 5318 /* All cells have 3 faces */ 5319 for(c = cStart; c < cEnd; ++c) { 5320 for(r = 0; r < 4; ++r) { 5321 const PetscInt newp = (c - cStart)*4 + r; 5322 5323 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5324 } 5325 } 5326 /* Split faces have 2 vertices and the same cells as the parent */ 5327 for(f = fStart; f < fEnd; ++f) { 5328 for(r = 0; r < 2; ++r) { 5329 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5330 PetscInt size; 5331 5332 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5333 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5334 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5335 } 5336 } 5337 /* Interior faces have 2 vertices and 2 cells */ 5338 for(c = cStart; c < cEnd; ++c) { 5339 for(r = 0; r < 3; ++r) { 5340 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5341 5342 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5343 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5344 } 5345 } 5346 /* Old vertices have identical supports */ 5347 for(v = vStart; v < vEnd; ++v) { 5348 const PetscInt newp = vStartNew + (v - vStart); 5349 PetscInt size; 5350 5351 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5352 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5353 } 5354 /* Face vertices have 2 + cells*2 supports */ 5355 for(f = fStart; f < fEnd; ++f) { 5356 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5357 PetscInt size; 5358 5359 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5360 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5361 } 5362 break; 5363 case 2: 5364 /* Hex 2D */ 5365 /* All cells have 4 faces */ 5366 for(c = cStart; c < cEnd; ++c) { 5367 for(r = 0; r < 4; ++r) { 5368 const PetscInt newp = (c - cStart)*4 + r; 5369 5370 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5371 } 5372 } 5373 /* Split faces have 2 vertices and the same cells as the parent */ 5374 for(f = fStart; f < fEnd; ++f) { 5375 for(r = 0; r < 2; ++r) { 5376 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5377 PetscInt size; 5378 5379 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5380 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5381 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5382 } 5383 } 5384 /* Interior faces have 2 vertices and 2 cells */ 5385 for(c = cStart; c < cEnd; ++c) { 5386 for(r = 0; r < 4; ++r) { 5387 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5388 5389 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5390 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5391 } 5392 } 5393 /* Old vertices have identical supports */ 5394 for(v = vStart; v < vEnd; ++v) { 5395 const PetscInt newp = vStartNew + (v - vStart); 5396 PetscInt size; 5397 5398 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5399 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5400 } 5401 /* Face vertices have 2 + cells supports */ 5402 for(f = fStart; f < fEnd; ++f) { 5403 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5404 PetscInt size; 5405 5406 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5407 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5408 } 5409 /* Cell vertices have 4 supports */ 5410 for(c = cStart; c < cEnd; ++c) { 5411 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5412 5413 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5414 } 5415 break; 5416 case 3: 5417 /* Hybrid 2D */ 5418 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5419 cMax = PetscMin(cEnd, cMax); 5420 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5421 fMax = PetscMin(fEnd, fMax); 5422 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5423 /* Interior cells have 3 faces */ 5424 for(c = cStart; c < cMax; ++c) { 5425 for(r = 0; r < 4; ++r) { 5426 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5427 5428 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5429 } 5430 } 5431 /* Hybrid cells have 4 faces */ 5432 for(c = cMax; c < cEnd; ++c) { 5433 for(r = 0; r < 2; ++r) { 5434 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5435 5436 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5437 } 5438 } 5439 /* Interior split faces have 2 vertices and the same cells as the parent */ 5440 for(f = fStart; f < fMax; ++f) { 5441 for(r = 0; r < 2; ++r) { 5442 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5443 PetscInt size; 5444 5445 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5446 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5447 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5448 } 5449 } 5450 /* Interior cell faces have 2 vertices and 2 cells */ 5451 for(c = cStart; c < cMax; ++c) { 5452 for(r = 0; r < 3; ++r) { 5453 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5454 5455 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5456 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5457 } 5458 } 5459 /* Hybrid faces have 2 vertices and the same cells */ 5460 for(f = fMax; f < fEnd; ++f) { 5461 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5462 PetscInt size; 5463 5464 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5465 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5466 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5467 } 5468 /* Hybrid cell faces have 2 vertices and 2 cells */ 5469 for(c = cMax; c < cEnd; ++c) { 5470 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5471 5472 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5473 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5474 } 5475 /* Old vertices have identical supports */ 5476 for(v = vStart; v < vEnd; ++v) { 5477 const PetscInt newp = vStartNew + (v - vStart); 5478 PetscInt size; 5479 5480 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5481 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5482 } 5483 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5484 for(f = fStart; f < fMax; ++f) { 5485 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5486 const PetscInt *support; 5487 PetscInt size, newSize = 2, s; 5488 5489 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5490 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5491 for(s = 0; s < size; ++s) { 5492 if (support[s] >= cMax) { 5493 newSize += 1; 5494 } else { 5495 newSize += 2; 5496 } 5497 } 5498 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5499 } 5500 break; 5501 default: 5502 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5503 } 5504 PetscFunctionReturn(0); 5505 } 5506 5507 #undef __FUNCT__ 5508 #define __FUNCT__ "CellRefinerSetCones" 5509 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5510 { 5511 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; 5512 PetscInt maxSupportSize, *supportRef; 5513 PetscErrorCode ierr; 5514 5515 PetscFunctionBegin; 5516 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5517 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5518 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5519 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5520 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5521 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5522 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5523 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5524 switch(refiner) { 5525 case 1: 5526 /* Simplicial 2D */ 5527 /* 5528 2 5529 |\ 5530 | \ 5531 | \ 5532 | \ 5533 | C \ 5534 | \ 5535 | \ 5536 2---1---1 5537 |\ D / \ 5538 | 2 0 \ 5539 |A \ / B \ 5540 0---0-------1 5541 */ 5542 /* All cells have 3 faces */ 5543 for(c = cStart; c < cEnd; ++c) { 5544 const PetscInt newp = cStartNew + (c - cStart)*4; 5545 const PetscInt *cone, *ornt; 5546 PetscInt coneNew[3], orntNew[3]; 5547 5548 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5549 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5550 /* A triangle */ 5551 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5552 orntNew[0] = ornt[0]; 5553 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5554 orntNew[1] = -2; 5555 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5556 orntNew[2] = ornt[2]; 5557 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5558 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5559 #if 1 5560 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); 5561 for(p = 0; p < 3; ++p) { 5562 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); 5563 } 5564 #endif 5565 /* B triangle */ 5566 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5567 orntNew[0] = ornt[0]; 5568 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5569 orntNew[1] = ornt[1]; 5570 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5571 orntNew[2] = -2; 5572 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5573 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5574 #if 1 5575 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); 5576 for(p = 0; p < 3; ++p) { 5577 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); 5578 } 5579 #endif 5580 /* C triangle */ 5581 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5582 orntNew[0] = -2; 5583 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5584 orntNew[1] = ornt[1]; 5585 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5586 orntNew[2] = ornt[2]; 5587 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5588 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5589 #if 1 5590 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); 5591 for(p = 0; p < 3; ++p) { 5592 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); 5593 } 5594 #endif 5595 /* D triangle */ 5596 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5597 orntNew[0] = 0; 5598 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5599 orntNew[1] = 0; 5600 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5601 orntNew[2] = 0; 5602 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5603 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5604 #if 1 5605 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); 5606 for(p = 0; p < 3; ++p) { 5607 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); 5608 } 5609 #endif 5610 } 5611 /* Split faces have 2 vertices and the same cells as the parent */ 5612 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5613 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5614 for(f = fStart; f < fEnd; ++f) { 5615 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5616 5617 for(r = 0; r < 2; ++r) { 5618 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5619 const PetscInt *cone, *support; 5620 PetscInt coneNew[2], coneSize, c, supportSize, s; 5621 5622 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5623 coneNew[0] = vStartNew + (cone[0] - vStart); 5624 coneNew[1] = vStartNew + (cone[1] - vStart); 5625 coneNew[(r+1)%2] = newv; 5626 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5627 #if 1 5628 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5629 for(p = 0; p < 2; ++p) { 5630 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); 5631 } 5632 #endif 5633 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5634 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5635 for(s = 0; s < supportSize; ++s) { 5636 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5637 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5638 for(c = 0; c < coneSize; ++c) { 5639 if (cone[c] == f) { 5640 break; 5641 } 5642 } 5643 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5644 } 5645 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5646 #if 1 5647 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5648 for(p = 0; p < supportSize; ++p) { 5649 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); 5650 } 5651 #endif 5652 } 5653 } 5654 /* Interior faces have 2 vertices and 2 cells */ 5655 for(c = cStart; c < cEnd; ++c) { 5656 const PetscInt *cone; 5657 5658 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5659 for(r = 0; r < 3; ++r) { 5660 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5661 PetscInt coneNew[2]; 5662 PetscInt supportNew[2]; 5663 5664 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5665 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5666 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5667 #if 1 5668 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5669 for(p = 0; p < 2; ++p) { 5670 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); 5671 } 5672 #endif 5673 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5674 supportNew[1] = (c - cStart)*4 + 3; 5675 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5676 #if 1 5677 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5678 for(p = 0; p < 2; ++p) { 5679 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); 5680 } 5681 #endif 5682 } 5683 } 5684 /* Old vertices have identical supports */ 5685 for(v = vStart; v < vEnd; ++v) { 5686 const PetscInt newp = vStartNew + (v - vStart); 5687 const PetscInt *support, *cone; 5688 PetscInt size, s; 5689 5690 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5691 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5692 for(s = 0; s < size; ++s) { 5693 PetscInt r = 0; 5694 5695 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5696 if (cone[1] == v) r = 1; 5697 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5698 } 5699 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5700 #if 1 5701 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5702 for(p = 0; p < size; ++p) { 5703 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); 5704 } 5705 #endif 5706 } 5707 /* Face vertices have 2 + cells*2 supports */ 5708 for(f = fStart; f < fEnd; ++f) { 5709 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5710 const PetscInt *cone, *support; 5711 PetscInt size, s; 5712 5713 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5714 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5715 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5716 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5717 for(s = 0; s < size; ++s) { 5718 PetscInt r = 0; 5719 5720 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5721 if (cone[1] == f) r = 1; 5722 else if (cone[2] == f) r = 2; 5723 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5724 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5725 } 5726 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5727 #if 1 5728 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5729 for(p = 0; p < 2+size*2; ++p) { 5730 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); 5731 } 5732 #endif 5733 } 5734 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5735 break; 5736 case 2: 5737 /* Hex 2D */ 5738 /* 5739 3---------2---------2 5740 | | | 5741 | D 2 C | 5742 | | | 5743 3----3----0----1----1 5744 | | | 5745 | A 0 B | 5746 | | | 5747 0---------0---------1 5748 */ 5749 /* All cells have 4 faces */ 5750 for(c = cStart; c < cEnd; ++c) { 5751 const PetscInt newp = (c - cStart)*4; 5752 const PetscInt *cone, *ornt; 5753 PetscInt coneNew[4], orntNew[4]; 5754 5755 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5756 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5757 /* A quad */ 5758 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5759 orntNew[0] = ornt[0]; 5760 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5761 orntNew[1] = 0; 5762 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5763 orntNew[2] = -2; 5764 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5765 orntNew[3] = ornt[3]; 5766 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5767 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5768 #if 1 5769 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); 5770 for(p = 0; p < 4; ++p) { 5771 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); 5772 } 5773 #endif 5774 /* B quad */ 5775 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5776 orntNew[0] = ornt[0]; 5777 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5778 orntNew[1] = ornt[1]; 5779 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5780 orntNew[2] = 0; 5781 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5782 orntNew[3] = -2; 5783 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5784 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5785 #if 1 5786 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); 5787 for(p = 0; p < 4; ++p) { 5788 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); 5789 } 5790 #endif 5791 /* C quad */ 5792 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5793 orntNew[0] = -2; 5794 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5795 orntNew[1] = ornt[1]; 5796 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5797 orntNew[2] = ornt[2]; 5798 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5799 orntNew[3] = 0; 5800 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5801 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5802 #if 1 5803 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); 5804 for(p = 0; p < 4; ++p) { 5805 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); 5806 } 5807 #endif 5808 /* D quad */ 5809 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5810 orntNew[0] = 0; 5811 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5812 orntNew[1] = -2; 5813 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5814 orntNew[2] = ornt[2]; 5815 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 5816 orntNew[3] = ornt[3]; 5817 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5818 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5819 #if 1 5820 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); 5821 for(p = 0; p < 4; ++p) { 5822 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); 5823 } 5824 #endif 5825 } 5826 /* Split faces have 2 vertices and the same cells as the parent */ 5827 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5828 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5829 for(f = fStart; f < fEnd; ++f) { 5830 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5831 5832 for(r = 0; r < 2; ++r) { 5833 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5834 const PetscInt *cone, *support; 5835 PetscInt coneNew[2], coneSize, c, supportSize, s; 5836 5837 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5838 coneNew[0] = vStartNew + (cone[0] - vStart); 5839 coneNew[1] = vStartNew + (cone[1] - vStart); 5840 coneNew[(r+1)%2] = newv; 5841 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5842 #if 1 5843 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5844 for(p = 0; p < 2; ++p) { 5845 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); 5846 } 5847 #endif 5848 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5849 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5850 for(s = 0; s < supportSize; ++s) { 5851 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5852 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5853 for(c = 0; c < coneSize; ++c) { 5854 if (cone[c] == f) { 5855 break; 5856 } 5857 } 5858 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 5859 } 5860 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5861 #if 1 5862 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5863 for(p = 0; p < supportSize; ++p) { 5864 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); 5865 } 5866 #endif 5867 } 5868 } 5869 /* Interior faces have 2 vertices and 2 cells */ 5870 for(c = cStart; c < cEnd; ++c) { 5871 const PetscInt *cone; 5872 PetscInt coneNew[2], supportNew[2]; 5873 5874 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5875 for(r = 0; r < 4; ++r) { 5876 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5877 5878 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5879 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5880 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5881 #if 1 5882 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5883 for(p = 0; p < 2; ++p) { 5884 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); 5885 } 5886 #endif 5887 supportNew[0] = (c - cStart)*4 + r; 5888 supportNew[1] = (c - cStart)*4 + (r+1)%4; 5889 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5890 #if 1 5891 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5892 for(p = 0; p < 2; ++p) { 5893 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); 5894 } 5895 #endif 5896 } 5897 } 5898 /* Old vertices have identical supports */ 5899 for(v = vStart; v < vEnd; ++v) { 5900 const PetscInt newp = vStartNew + (v - vStart); 5901 const PetscInt *support, *cone; 5902 PetscInt size, s; 5903 5904 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5905 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5906 for(s = 0; s < size; ++s) { 5907 PetscInt r = 0; 5908 5909 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5910 if (cone[1] == v) r = 1; 5911 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5912 } 5913 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5914 #if 1 5915 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5916 for(p = 0; p < size; ++p) { 5917 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); 5918 } 5919 #endif 5920 } 5921 /* Face vertices have 2 + cells supports */ 5922 for(f = fStart; f < fEnd; ++f) { 5923 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5924 const PetscInt *cone, *support; 5925 PetscInt size, s; 5926 5927 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5928 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5929 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5930 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5931 for(s = 0; s < size; ++s) { 5932 PetscInt r = 0; 5933 5934 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5935 if (cone[1] == f) r = 1; 5936 else if (cone[2] == f) r = 2; 5937 else if (cone[3] == f) r = 3; 5938 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 5939 } 5940 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5941 #if 1 5942 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5943 for(p = 0; p < 2+size; ++p) { 5944 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); 5945 } 5946 #endif 5947 } 5948 /* Cell vertices have 4 supports */ 5949 for(c = cStart; c < cEnd; ++c) { 5950 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5951 PetscInt supportNew[4]; 5952 5953 for(r = 0; r < 4; ++r) { 5954 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5955 } 5956 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5957 } 5958 break; 5959 case 3: 5960 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5961 cMax = PetscMin(cEnd, cMax); 5962 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5963 fMax = PetscMin(fEnd, fMax); 5964 /* Interior cells have 3 faces */ 5965 for(c = cStart; c < cMax; ++c) { 5966 const PetscInt newp = cStartNew + (c - cStart)*4; 5967 const PetscInt *cone, *ornt; 5968 PetscInt coneNew[3], orntNew[3]; 5969 5970 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5971 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5972 /* A triangle */ 5973 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5974 orntNew[0] = ornt[0]; 5975 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 5976 orntNew[1] = -2; 5977 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5978 orntNew[2] = ornt[2]; 5979 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5980 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5981 #if 1 5982 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); 5983 for(p = 0; p < 3; ++p) { 5984 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); 5985 } 5986 #endif 5987 /* B triangle */ 5988 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5989 orntNew[0] = ornt[0]; 5990 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5991 orntNew[1] = ornt[1]; 5992 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 5993 orntNew[2] = -2; 5994 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5995 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5996 #if 1 5997 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); 5998 for(p = 0; p < 3; ++p) { 5999 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); 6000 } 6001 #endif 6002 /* C triangle */ 6003 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6004 orntNew[0] = -2; 6005 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6006 orntNew[1] = ornt[1]; 6007 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6008 orntNew[2] = ornt[2]; 6009 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6010 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6011 #if 1 6012 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); 6013 for(p = 0; p < 3; ++p) { 6014 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); 6015 } 6016 #endif 6017 /* D triangle */ 6018 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6019 orntNew[0] = 0; 6020 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6021 orntNew[1] = 0; 6022 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6023 orntNew[2] = 0; 6024 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6025 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6026 #if 1 6027 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); 6028 for(p = 0; p < 3; ++p) { 6029 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); 6030 } 6031 #endif 6032 } 6033 /* 6034 2----3----3 6035 | | 6036 | B | 6037 | | 6038 0----4--- 1 6039 | | 6040 | A | 6041 | | 6042 0----2----1 6043 */ 6044 /* Hybrid cells have 4 faces */ 6045 for(c = cMax; c < cEnd; ++c) { 6046 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6047 const PetscInt *cone, *ornt; 6048 PetscInt coneNew[4], orntNew[4]; 6049 6050 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6051 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6052 /* A quad */ 6053 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6054 orntNew[0] = ornt[0]; 6055 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6056 orntNew[1] = ornt[1]; 6057 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6058 orntNew[2] = 0; 6059 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6060 orntNew[3] = 0; 6061 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6062 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6063 #if 1 6064 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); 6065 for(p = 0; p < 4; ++p) { 6066 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); 6067 } 6068 #endif 6069 /* B quad */ 6070 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6071 orntNew[0] = ornt[0]; 6072 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6073 orntNew[1] = ornt[1]; 6074 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6075 orntNew[2] = 0; 6076 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6077 orntNew[3] = 0; 6078 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6079 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6080 #if 1 6081 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); 6082 for(p = 0; p < 4; ++p) { 6083 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); 6084 } 6085 #endif 6086 } 6087 /* Interior split faces have 2 vertices and the same cells as the parent */ 6088 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6089 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6090 for(f = fStart; f < fMax; ++f) { 6091 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6092 6093 for(r = 0; r < 2; ++r) { 6094 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6095 const PetscInt *cone, *support; 6096 PetscInt coneNew[2], coneSize, c, supportSize, s; 6097 6098 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6099 coneNew[0] = vStartNew + (cone[0] - vStart); 6100 coneNew[1] = vStartNew + (cone[1] - vStart); 6101 coneNew[(r+1)%2] = newv; 6102 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6103 #if 1 6104 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6105 for(p = 0; p < 2; ++p) { 6106 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); 6107 } 6108 #endif 6109 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6110 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6111 for(s = 0; s < supportSize; ++s) { 6112 if (support[s] >= cMax) { 6113 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6114 } else { 6115 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6116 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6117 for(c = 0; c < coneSize; ++c) { 6118 if (cone[c] == f) { 6119 break; 6120 } 6121 } 6122 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6123 } 6124 } 6125 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6126 #if 1 6127 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6128 for(p = 0; p < supportSize; ++p) { 6129 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); 6130 } 6131 #endif 6132 } 6133 } 6134 /* Interior cell faces have 2 vertices and 2 cells */ 6135 for(c = cStart; c < cMax; ++c) { 6136 const PetscInt *cone; 6137 6138 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6139 for(r = 0; r < 3; ++r) { 6140 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6141 PetscInt coneNew[2]; 6142 PetscInt supportNew[2]; 6143 6144 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6145 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6146 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6147 #if 1 6148 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6149 for(p = 0; p < 2; ++p) { 6150 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); 6151 } 6152 #endif 6153 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6154 supportNew[1] = (c - cStart)*4 + 3; 6155 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6156 #if 1 6157 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6158 for(p = 0; p < 2; ++p) { 6159 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); 6160 } 6161 #endif 6162 } 6163 } 6164 /* Interior hybrid faces have 2 vertices and the same cells */ 6165 for(f = fMax; f < fEnd; ++f) { 6166 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6167 const PetscInt *cone; 6168 const PetscInt *support; 6169 PetscInt coneNew[2]; 6170 PetscInt supportNew[2]; 6171 PetscInt size, s, r; 6172 6173 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6174 coneNew[0] = vStartNew + (cone[0] - vStart); 6175 coneNew[1] = vStartNew + (cone[1] - vStart); 6176 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6177 #if 1 6178 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6179 for(p = 0; p < 2; ++p) { 6180 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); 6181 } 6182 #endif 6183 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6184 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6185 for(s = 0; s < size; ++s) { 6186 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6187 for(r = 0; r < 2; ++r) { 6188 if (cone[r+2] == f) break; 6189 } 6190 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6191 } 6192 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6193 #if 1 6194 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6195 for(p = 0; p < size; ++p) { 6196 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); 6197 } 6198 #endif 6199 } 6200 /* Cell hybrid faces have 2 vertices and 2 cells */ 6201 for(c = cMax; c < cEnd; ++c) { 6202 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6203 const PetscInt *cone; 6204 PetscInt coneNew[2]; 6205 PetscInt supportNew[2]; 6206 6207 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6208 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6209 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6210 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6211 #if 1 6212 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6213 for(p = 0; p < 2; ++p) { 6214 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); 6215 } 6216 #endif 6217 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6218 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6219 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6220 #if 1 6221 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6222 for(p = 0; p < 2; ++p) { 6223 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); 6224 } 6225 #endif 6226 } 6227 /* Old vertices have identical supports */ 6228 for(v = vStart; v < vEnd; ++v) { 6229 const PetscInt newp = vStartNew + (v - vStart); 6230 const PetscInt *support, *cone; 6231 PetscInt size, s; 6232 6233 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6234 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6235 for(s = 0; s < size; ++s) { 6236 if (support[s] >= fMax) { 6237 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6238 } else { 6239 PetscInt r = 0; 6240 6241 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6242 if (cone[1] == v) r = 1; 6243 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6244 } 6245 } 6246 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6247 #if 1 6248 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6249 for(p = 0; p < size; ++p) { 6250 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); 6251 } 6252 #endif 6253 } 6254 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6255 for(f = fStart; f < fMax; ++f) { 6256 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6257 const PetscInt *cone, *support; 6258 PetscInt size, newSize = 2, s; 6259 6260 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6261 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6262 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6263 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6264 for(s = 0; s < size; ++s) { 6265 PetscInt r = 0; 6266 6267 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6268 if (support[s] >= cMax) { 6269 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6270 newSize += 1; 6271 } else { 6272 if (cone[1] == f) r = 1; 6273 else if (cone[2] == f) r = 2; 6274 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6275 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6276 newSize += 2; 6277 } 6278 } 6279 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6280 #if 1 6281 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6282 for(p = 0; p < newSize; ++p) { 6283 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); 6284 } 6285 #endif 6286 } 6287 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6288 break; 6289 default: 6290 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6291 } 6292 PetscFunctionReturn(0); 6293 } 6294 6295 #undef __FUNCT__ 6296 #define __FUNCT__ "CellRefinerSetCoordinates" 6297 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6298 { 6299 PetscSection coordSection, coordSectionNew; 6300 Vec coordinates, coordinatesNew; 6301 PetscScalar *coords, *coordsNew; 6302 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6303 PetscErrorCode ierr; 6304 6305 PetscFunctionBegin; 6306 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6307 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6308 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6309 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6310 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6311 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6312 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6313 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6314 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6315 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6316 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6317 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6318 if (fMax < 0) fMax = fEnd; 6319 switch(refiner) { 6320 case 1: 6321 case 2: 6322 case 3: 6323 /* Simplicial and Hex 2D */ 6324 /* All vertices have the dim coordinates */ 6325 for(v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6326 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6327 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6328 } 6329 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6330 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6331 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6332 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6333 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6334 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6335 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6336 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6337 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6338 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6339 /* Old vertices have the same coordinates */ 6340 for(v = vStart; v < vEnd; ++v) { 6341 const PetscInt newv = vStartNew + (v - vStart); 6342 PetscInt off, offnew, d; 6343 6344 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6345 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6346 for(d = 0; d < dim; ++d) { 6347 coordsNew[offnew+d] = coords[off+d]; 6348 } 6349 } 6350 /* Face vertices have the average of endpoint coordinates */ 6351 for(f = fStart; f < fMax; ++f) { 6352 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6353 const PetscInt *cone; 6354 PetscInt coneSize, offA, offB, offnew, d; 6355 6356 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6357 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6358 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6359 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6360 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6361 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6362 for(d = 0; d < dim; ++d) { 6363 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6364 } 6365 } 6366 /* Just Hex 2D */ 6367 if (refiner == 2) { 6368 /* Cell vertices have the average of corner coordinates */ 6369 for(c = cStart; c < cEnd; ++c) { 6370 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6371 PetscInt *cone = PETSC_NULL; 6372 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6373 6374 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6375 for(p = 0; p < closureSize*2; p += 2) { 6376 const PetscInt point = cone[p]; 6377 if ((point >= vStart) && (point < vEnd)) { 6378 cone[coneSize++] = point; 6379 } 6380 } 6381 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6382 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6383 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6384 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6385 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6386 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6387 for(d = 0; d < dim; ++d) { 6388 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6389 } 6390 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6391 } 6392 } 6393 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6394 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6395 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6396 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6397 break; 6398 default: 6399 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6400 } 6401 PetscFunctionReturn(0); 6402 } 6403 6404 #undef __FUNCT__ 6405 #define __FUNCT__ "DMPlexCreateProcessSF" 6406 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6407 { 6408 PetscInt numRoots, numLeaves, l; 6409 const PetscInt *localPoints; 6410 const PetscSFNode *remotePoints; 6411 PetscInt *localPointsNew; 6412 PetscSFNode *remotePointsNew; 6413 PetscInt *ranks, *ranksNew; 6414 PetscErrorCode ierr; 6415 6416 PetscFunctionBegin; 6417 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6418 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6419 for(l = 0; l < numLeaves; ++l) { 6420 ranks[l] = remotePoints[l].rank; 6421 } 6422 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6423 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6424 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6425 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6426 for(l = 0; l < numLeaves; ++l) { 6427 ranksNew[l] = ranks[l]; 6428 localPointsNew[l] = l; 6429 remotePointsNew[l].index = 0; 6430 remotePointsNew[l].rank = ranksNew[l]; 6431 } 6432 ierr = PetscFree(ranks);CHKERRQ(ierr); 6433 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6434 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6435 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6436 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6437 PetscFunctionReturn(0); 6438 } 6439 6440 #undef __FUNCT__ 6441 #define __FUNCT__ "CellRefinerCreateSF" 6442 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6443 { 6444 PetscSF sf, sfNew, sfProcess; 6445 IS processRanks; 6446 MPI_Datatype depthType; 6447 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6448 const PetscInt *localPoints, *neighbors; 6449 const PetscSFNode *remotePoints; 6450 PetscInt *localPointsNew; 6451 PetscSFNode *remotePointsNew; 6452 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6453 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6454 PetscErrorCode ierr; 6455 6456 PetscFunctionBegin; 6457 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6458 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6459 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6460 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6461 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6462 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6463 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6464 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6465 switch(refiner) { 6466 case 3: 6467 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6468 cMax = PetscMin(cEnd, cMax); 6469 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6470 fMax = PetscMin(fEnd, fMax); 6471 } 6472 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6473 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6474 /* Caculate size of new SF */ 6475 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6476 if (numRoots < 0) PetscFunctionReturn(0); 6477 for(l = 0; l < numLeaves; ++l) { 6478 const PetscInt p = localPoints[l]; 6479 6480 switch(refiner) { 6481 case 1: 6482 /* Simplicial 2D */ 6483 if ((p >= vStart) && (p < vEnd)) { 6484 /* Old vertices stay the same */ 6485 ++numLeavesNew; 6486 } else if ((p >= fStart) && (p < fEnd)) { 6487 /* Old faces add new faces and vertex */ 6488 numLeavesNew += 1 + 2; 6489 } else if ((p >= cStart) && (p < cEnd)) { 6490 /* Old cells add new cells and interior faces */ 6491 numLeavesNew += 4 + 3; 6492 } 6493 break; 6494 case 2: 6495 /* Hex 2D */ 6496 if ((p >= vStart) && (p < vEnd)) { 6497 /* Old vertices stay the same */ 6498 ++numLeavesNew; 6499 } else if ((p >= fStart) && (p < fEnd)) { 6500 /* Old faces add new faces and vertex */ 6501 numLeavesNew += 1 + 2; 6502 } else if ((p >= cStart) && (p < cEnd)) { 6503 /* Old cells add new cells and interior faces */ 6504 numLeavesNew += 4 + 4; 6505 } 6506 break; 6507 default: 6508 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6509 } 6510 } 6511 /* Communicate depthSizes for each remote rank */ 6512 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6513 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6514 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6515 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); 6516 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6517 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6518 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6519 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6520 for(n = 0; n < numNeighbors; ++n) { 6521 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6522 } 6523 depthSizeOld[depth] = cMax; 6524 depthSizeOld[0] = vMax; 6525 depthSizeOld[depth-1] = fMax; 6526 depthSizeOld[1] = eMax; 6527 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6528 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6529 depthSizeOld[depth] = cEnd - cStart; 6530 depthSizeOld[0] = vEnd - vStart; 6531 depthSizeOld[depth-1] = fEnd - fStart; 6532 depthSizeOld[1] = eEnd - eStart; 6533 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6534 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6535 for(n = 0; n < numNeighbors; ++n) { 6536 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6537 } 6538 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6539 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6540 /* Calculate new point SF */ 6541 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6542 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6543 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6544 for(l = 0, m = 0; l < numLeaves; ++l) { 6545 PetscInt p = localPoints[l]; 6546 PetscInt rp = remotePoints[l].index, n; 6547 PetscMPIInt rrank = remotePoints[l].rank; 6548 6549 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6550 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6551 switch(refiner) { 6552 case 1: 6553 /* Simplicial 2D */ 6554 if ((p >= vStart) && (p < vEnd)) { 6555 /* Old vertices stay the same */ 6556 localPointsNew[m] = vStartNew + (p - vStart); 6557 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6558 remotePointsNew[m].rank = rrank; 6559 ++m; 6560 } else if ((p >= fStart) && (p < fEnd)) { 6561 /* Old faces add new faces and vertex */ 6562 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6563 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6564 remotePointsNew[m].rank = rrank; 6565 ++m; 6566 for(r = 0; r < 2; ++r, ++m) { 6567 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6568 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6569 remotePointsNew[m].rank = rrank; 6570 } 6571 } else if ((p >= cStart) && (p < cEnd)) { 6572 /* Old cells add new cells and interior faces */ 6573 for(r = 0; r < 4; ++r, ++m) { 6574 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6575 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6576 remotePointsNew[m].rank = rrank; 6577 } 6578 for(r = 0; r < 3; ++r, ++m) { 6579 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6580 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6581 remotePointsNew[m].rank = rrank; 6582 } 6583 } 6584 break; 6585 case 2: 6586 /* Hex 2D */ 6587 if ((p >= vStart) && (p < vEnd)) { 6588 /* Old vertices stay the same */ 6589 localPointsNew[m] = vStartNew + (p - vStart); 6590 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6591 remotePointsNew[m].rank = rrank; 6592 ++m; 6593 } else if ((p >= fStart) && (p < fEnd)) { 6594 /* Old faces add new faces and vertex */ 6595 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6596 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6597 remotePointsNew[m].rank = rrank; 6598 ++m; 6599 for(r = 0; r < 2; ++r, ++m) { 6600 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6601 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6602 remotePointsNew[m].rank = rrank; 6603 } 6604 } else if ((p >= cStart) && (p < cEnd)) { 6605 /* Old cells add new cells and interior faces */ 6606 for(r = 0; r < 4; ++r, ++m) { 6607 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6608 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6609 remotePointsNew[m].rank = rrank; 6610 } 6611 for(r = 0; r < 4; ++r, ++m) { 6612 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6613 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6614 remotePointsNew[m].rank = rrank; 6615 } 6616 } 6617 break; 6618 case 3: 6619 /* Hybrid simplicial 2D */ 6620 if ((p >= vStart) && (p < vEnd)) { 6621 /* Old vertices stay the same */ 6622 localPointsNew[m] = vStartNew + (p - vStart); 6623 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6624 remotePointsNew[m].rank = rrank; 6625 ++m; 6626 } else if ((p >= fStart) && (p < fMax)) { 6627 /* Old interior faces add new faces and vertex */ 6628 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6629 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6630 remotePointsNew[m].rank = rrank; 6631 ++m; 6632 for(r = 0; r < 2; ++r, ++m) { 6633 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6634 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6635 remotePointsNew[m].rank = rrank; 6636 } 6637 } else if ((p >= fMax) && (p < fEnd)) { 6638 /* Old hybrid faces stay the same */ 6639 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6640 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6641 remotePointsNew[m].rank = rrank; 6642 ++m; 6643 } else if ((p >= cStart) && (p < cMax)) { 6644 /* Old interior cells add new cells and interior faces */ 6645 for(r = 0; r < 4; ++r, ++m) { 6646 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6647 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6648 remotePointsNew[m].rank = rrank; 6649 } 6650 for(r = 0; r < 3; ++r, ++m) { 6651 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6652 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6653 remotePointsNew[m].rank = rrank; 6654 } 6655 } else if ((p >= cStart) && (p < cMax)) { 6656 /* Old hybrid cells add new cells and hybrid face */ 6657 for(r = 0; r < 2; ++r, ++m) { 6658 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6659 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6660 remotePointsNew[m].rank = rrank; 6661 } 6662 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6663 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]); 6664 remotePointsNew[m].rank = rrank; 6665 ++m; 6666 } 6667 break; 6668 default: 6669 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6670 } 6671 } 6672 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6673 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6674 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6675 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6676 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6677 PetscFunctionReturn(0); 6678 } 6679 6680 #undef __FUNCT__ 6681 #define __FUNCT__ "CellRefinerCreateLabels" 6682 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6683 { 6684 PetscInt numLabels, l; 6685 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6686 PetscErrorCode ierr; 6687 6688 PetscFunctionBegin; 6689 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6690 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6691 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6692 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6693 cStartNew = 0; 6694 vStartNew = depthSize[2]; 6695 fStartNew = depthSize[2] + depthSize[0]; 6696 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6697 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6698 switch(refiner) { 6699 case 3: 6700 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6701 cMax = PetscMin(cEnd, cMax); 6702 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6703 fMax = PetscMin(fEnd, fMax); 6704 } 6705 for(l = 0; l < numLabels; ++l) { 6706 DMLabel label, labelNew; 6707 const char *lname; 6708 PetscBool isDepth; 6709 IS valueIS; 6710 const PetscInt *values; 6711 PetscInt numValues, val; 6712 6713 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6714 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6715 if (isDepth) continue; 6716 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6717 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6718 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6719 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6720 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6721 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6722 for(val = 0; val < numValues; ++val) { 6723 IS pointIS; 6724 const PetscInt *points; 6725 PetscInt numPoints, n; 6726 6727 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6728 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6729 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6730 for(n = 0; n < numPoints; ++n) { 6731 const PetscInt p = points[n]; 6732 switch(refiner) { 6733 case 1: 6734 /* Simplicial 2D */ 6735 if ((p >= vStart) && (p < vEnd)) { 6736 /* Old vertices stay the same */ 6737 newp = vStartNew + (p - vStart); 6738 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6739 } else if ((p >= fStart) && (p < fEnd)) { 6740 /* Old faces add new faces and vertex */ 6741 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6742 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6743 for(r = 0; r < 2; ++r) { 6744 newp = fStartNew + (p - fStart)*2 + r; 6745 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6746 } 6747 } else if ((p >= cStart) && (p < cEnd)) { 6748 /* Old cells add new cells and interior faces */ 6749 for(r = 0; r < 4; ++r) { 6750 newp = cStartNew + (p - cStart)*4 + r; 6751 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6752 } 6753 for(r = 0; r < 3; ++r) { 6754 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6755 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6756 } 6757 } 6758 break; 6759 case 2: 6760 /* Hex 2D */ 6761 if ((p >= vStart) && (p < vEnd)) { 6762 /* Old vertices stay the same */ 6763 newp = vStartNew + (p - vStart); 6764 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6765 } else if ((p >= fStart) && (p < fEnd)) { 6766 /* Old faces add new faces and vertex */ 6767 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6768 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6769 for(r = 0; r < 2; ++r) { 6770 newp = fStartNew + (p - fStart)*2 + r; 6771 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6772 } 6773 } else if ((p >= cStart) && (p < cEnd)) { 6774 /* Old cells add new cells and interior faces and vertex */ 6775 for(r = 0; r < 4; ++r) { 6776 newp = cStartNew + (p - cStart)*4 + r; 6777 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6778 } 6779 for(r = 0; r < 4; ++r) { 6780 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6781 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6782 } 6783 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 6784 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6785 } 6786 break; 6787 case 3: 6788 /* Hybrid simplicial 2D */ 6789 if ((p >= vStart) && (p < vEnd)) { 6790 /* Old vertices stay the same */ 6791 newp = vStartNew + (p - vStart); 6792 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6793 } else if ((p >= fStart) && (p < fMax)) { 6794 /* Old interior faces add new faces and vertex */ 6795 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6796 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6797 for(r = 0; r < 2; ++r) { 6798 newp = fStartNew + (p - fStart)*2 + r; 6799 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6800 } 6801 } else if ((p >= fMax) && (p < fEnd)) { 6802 /* Old hybrid faces stay the same */ 6803 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 6804 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6805 } else if ((p >= cStart) && (p < cMax)) { 6806 /* Old interior cells add new cells and interior faces */ 6807 for(r = 0; r < 4; ++r) { 6808 newp = cStartNew + (p - cStart)*4 + r; 6809 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6810 } 6811 for(r = 0; r < 3; ++r) { 6812 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6813 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6814 } 6815 } else if ((p >= cMax) && (p < cEnd)) { 6816 /* Old hybrid cells add new cells and hybrid face */ 6817 for(r = 0; r < 2; ++r) { 6818 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 6819 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6820 } 6821 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6822 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6823 } 6824 break; 6825 default: 6826 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6827 } 6828 } 6829 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 6830 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 6831 } 6832 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 6833 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 6834 if (0) { 6835 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 6836 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6837 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6838 } 6839 } 6840 PetscFunctionReturn(0); 6841 } 6842 6843 #undef __FUNCT__ 6844 #define __FUNCT__ "DMPlexRefine_Uniform" 6845 /* This will only work for interpolated meshes */ 6846 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 6847 { 6848 DM rdm; 6849 PetscInt *depthSize; 6850 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 6851 PetscErrorCode ierr; 6852 6853 PetscFunctionBegin; 6854 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 6855 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 6856 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6857 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 6858 /* Calculate number of new points of each depth */ 6859 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6860 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 6861 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 6862 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 6863 /* Step 1: Set chart */ 6864 for(d = 0; d <= depth; ++d) { 6865 pEnd += depthSize[d]; 6866 } 6867 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 6868 /* Step 2: Set cone/support sizes */ 6869 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6870 /* Step 3: Setup refined DM */ 6871 ierr = DMSetUp(rdm);CHKERRQ(ierr); 6872 /* Step 4: Set cones and supports */ 6873 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6874 /* Step 5: Stratify */ 6875 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 6876 /* Step 6: Set coordinates for vertices */ 6877 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6878 /* Step 7: Create pointSF */ 6879 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6880 /* Step 8: Create labels */ 6881 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6882 ierr = PetscFree(depthSize);CHKERRQ(ierr); 6883 6884 *dmRefined = rdm; 6885 #if 0 6886 DM_Plex *mesh = (DM_Plex *) dm->data; 6887 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 6888 /* ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); */ 6889 6890 PetscFunctionBegin; 6891 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6892 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 6893 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6894 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6895 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 6896 6897 /* Count number of new cells which are normal and extra */ 6898 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 6899 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 6900 for(c = cStart; c < cEnd2; ++c) { 6901 PetscInt n; 6902 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 6903 newNumCellsNormal += n; 6904 } 6905 for(c = cEnd2; c < cEnd; ++c) { 6906 PetscInt n; 6907 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 6908 newNumCellsExtra += n; 6909 } 6910 newNumCells = newNumCellsNormal + newNumCellsExtra; 6911 /* Count number of new vertices which are normal and extra */ 6912 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 6913 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 6914 for(c = cStart; c < cEnd; ++c) { 6915 PetscInt *closure = PETSC_NULL; 6916 PetscInt closureSize, numCorners = 0, p; 6917 6918 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6919 for(p = 0; p < closureSize*2; p += 2) { 6920 const PetscInt point = closure[p]; 6921 if ((point >= vStart) && (point < vEnd)) { 6922 closure[numCorners++] = point; 6923 } 6924 } 6925 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCell */ 6926 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6927 } 6928 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 6929 for(c = cEnd2; c < cEnd; ++c) { 6930 PetscInt *closure = PETSC_NULL; 6931 PetscInt closureSize, numCorners = 0, p; 6932 6933 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6934 for(p = 0; p < closureSize*2; p += 2) { 6935 const PetscInt point = closure[p]; 6936 if ((point >= vStart) && (point < vEnd)) { 6937 closure[numCorners++] = point; 6938 } 6939 } 6940 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCellUncensored */ 6941 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6942 } /* for */ 6943 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 6944 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 6945 6946 #if 1 6947 PetscInt oldNumCellsNormal = cEnd2 - cStart; 6948 PetscInt oldNumCellsExtra = cEnd - cEnd2; 6949 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 6950 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 6951 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 6952 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 6953 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 6954 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 6955 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 6956 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 6957 ierr = PetscSynchronizedFlush(comm); 6958 #endif 6959 6960 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 6961 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 6962 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 6963 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 6964 ierr = DMPlexGetHybridBounds(*dmRefined, newNumCellsNormal, PETSC_NULL, PETSC_NULL, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 6965 /* Set cone and support sizes for new normal cells */ 6966 PetscInt newCell = 0; 6967 for(c = cStart; c < cEnd2; ++c) { 6968 PetscInt coneSize, n, i; 6969 6970 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6971 ierr = CellRefinerGetNumSubcells(refiner, c, &n); /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 6972 for(i = 0; i < n; ++i, ++newCell) { 6973 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 6974 } 6975 6976 PetscInt *closure = PETSC_NULL; 6977 PetscInt closureSize, numCorners = 0, p; 6978 6979 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6980 for(p = 0; p < closureSize*2; p += 2) { 6981 const PetscInt point = closure[p]; 6982 if ((point >= vStart) && (point < vEnd)) { 6983 closure[numCorners++] = point; 6984 } 6985 } 6986 /* ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 6987 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6988 } 6989 6990 /* Reset current new cell value and loop over censored cells. */ 6991 curNewCell = _orderNewMesh->cellsCensored().min(); 6992 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 6993 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 6994 /* Set new cone and support sizes */ 6995 cV.clear(); 6996 sieve->cone(*c_iter, cV); 6997 const point_type* cone = cV.getPoints(); 6998 const int coneSize = cV.getSize(); 6999 7000 const point_type* newCells; 7001 int numNewCells = 0; 7002 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7003 7004 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7005 newSieve->setConeSize(curNewCell, coneSize); 7006 for(int iVertex=0; iVertex < coneSize; ++iVertex) { 7007 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 7008 } /* for */ 7009 } /* for */ 7010 } /* for */ 7011 newSieve->allocate(); 7012 7013 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 7014 7015 /* Create refined cells in new sieve. */ 7016 curNewCell = _orderNewMesh->cellsNormal().min(); 7017 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 7018 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 7019 cV.clear(); 7020 sieve->cone(*c_iter, cV); 7021 const point_type *cone = cV.getPoints(); 7022 const int coneSize = cV.getSize(); 7023 7024 const point_type* newCells; 7025 int numNewCells = 0; 7026 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7027 7028 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7029 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7030 } /* for */ 7031 } /* for */ 7032 curNewCell = _orderNewMesh->cellsCensored().min(); 7033 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7034 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7035 cV.clear(); 7036 sieve->cone(*c_iter, cV); 7037 const point_type *cone = cV.getPoints(); 7038 const int coneSize = cV.getSize(); 7039 7040 const point_type* newCells; 7041 int numNewCells = 0; 7042 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7043 7044 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7045 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7046 } /* for */ 7047 } /* for */ 7048 newSieve->symmetrize(); 7049 7050 /* Set coordinates in refined mesh. */ 7051 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 7052 assert(!coordinates.isNull()); 7053 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 7054 assert(!newCoordinates.isNull()); 7055 7056 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 7057 assert(vertices->size() > 0); 7058 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 7059 assert(spaceDim > 0); 7060 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 7061 7062 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 7063 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 7064 newCoordinates->setFiberDimension(*v_iter, spaceDim); 7065 } /* for */ 7066 newCoordinates->allocatePoint(); 7067 7068 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 7069 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7070 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7071 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7072 } /* for */ 7073 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 7074 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7075 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7076 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7077 } /* for */ 7078 7079 refiner.setCoordsNewVertices(newCoordinates, coordinates); 7080 7081 /* Create sensored depth */ 7082 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 7083 assert(!censoredLabel.isNull()); 7084 7085 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 7086 7087 newSieve->roots(depthVisitor); 7088 while(depthVisitor.isModified()) { 7089 /* FIX: Avoid the copy here somehow by fixing the traversal */ 7090 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 7091 7092 depthVisitor.clear(); 7093 newSieve->support(modifiedPoints, depthVisitor); 7094 } /* while */ 7095 /* Stratify refined mesh */ 7096 /* Calculate new point SF */ 7097 _calcNewOverlap(newMesh, mesh, refiner); 7098 /* Calculate new labels */ 7099 _createLabels(newMesh, mesh, refiner); 7100 #endif 7101 PetscFunctionReturn(0); 7102 } 7103 7104 #undef __FUNCT__ 7105 #define __FUNCT__ "DMPlexSetRefinementUniform" 7106 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7107 { 7108 DM_Plex *mesh = (DM_Plex *) dm->data; 7109 7110 PetscFunctionBegin; 7111 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7112 mesh->refinementUniform = refinementUniform; 7113 PetscFunctionReturn(0); 7114 } 7115 7116 #undef __FUNCT__ 7117 #define __FUNCT__ "DMPlexGetRefinementUniform" 7118 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7119 { 7120 DM_Plex *mesh = (DM_Plex *) dm->data; 7121 7122 PetscFunctionBegin; 7123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7124 PetscValidPointer(refinementUniform, 2); 7125 *refinementUniform = mesh->refinementUniform; 7126 PetscFunctionReturn(0); 7127 } 7128 7129 #undef __FUNCT__ 7130 #define __FUNCT__ "DMPlexSetRefinementLimit" 7131 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7132 { 7133 DM_Plex *mesh = (DM_Plex *) dm->data; 7134 7135 PetscFunctionBegin; 7136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7137 mesh->refinementLimit = refinementLimit; 7138 PetscFunctionReturn(0); 7139 } 7140 7141 #undef __FUNCT__ 7142 #define __FUNCT__ "DMPlexGetRefinementLimit" 7143 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7144 { 7145 DM_Plex *mesh = (DM_Plex *) dm->data; 7146 7147 PetscFunctionBegin; 7148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7149 PetscValidPointer(refinementLimit, 2); 7150 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7151 *refinementLimit = mesh->refinementLimit; 7152 PetscFunctionReturn(0); 7153 } 7154 7155 #undef __FUNCT__ 7156 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7157 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7158 { 7159 PetscInt dim, cStart, coneSize, cMax; 7160 PetscErrorCode ierr; 7161 7162 PetscFunctionBegin; 7163 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7164 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7165 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7166 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7167 switch(dim) { 7168 case 2: 7169 switch(coneSize) { 7170 case 3: 7171 if (cMax >= 0) { 7172 *cellRefiner = 3; /* Hybrid */ 7173 } else { 7174 *cellRefiner = 1; /* Triangular */ 7175 } 7176 break; 7177 case 4: 7178 if (cMax >= 0) { 7179 *cellRefiner = 4; /* Hybrid */ 7180 } else { 7181 *cellRefiner = 2; /* Quadrilateral */ 7182 } 7183 break; 7184 default: 7185 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7186 } 7187 break; 7188 default: 7189 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7190 } 7191 PetscFunctionReturn(0); 7192 } 7193 7194 #undef __FUNCT__ 7195 #define __FUNCT__ "DMRefine_Plex" 7196 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7197 { 7198 PetscReal refinementLimit; 7199 PetscInt dim, cStart, cEnd; 7200 char genname[1024], *name = PETSC_NULL; 7201 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7202 PetscErrorCode ierr; 7203 7204 PetscFunctionBegin; 7205 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7206 if (isUniform) { 7207 CellRefiner cellRefiner; 7208 7209 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7210 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7211 PetscFunctionReturn(0); 7212 } 7213 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7214 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7215 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7216 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7217 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7218 if (flg) {name = genname;} 7219 if (name) { 7220 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7221 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7222 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7223 } 7224 switch(dim) { 7225 case 2: 7226 if (!name || isTriangle) { 7227 #ifdef PETSC_HAVE_TRIANGLE 7228 double *maxVolumes; 7229 PetscInt c; 7230 7231 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7232 for (c = 0; c < cEnd-cStart; ++c) { 7233 maxVolumes[c] = refinementLimit; 7234 } 7235 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7236 #else 7237 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7238 #endif 7239 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7240 break; 7241 case 3: 7242 if (!name || isCTetgen) { 7243 #ifdef PETSC_HAVE_CTETGEN 7244 PetscReal *maxVolumes; 7245 PetscInt c; 7246 7247 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7248 for (c = 0; c < cEnd-cStart; ++c) { 7249 maxVolumes[c] = refinementLimit; 7250 } 7251 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7252 #else 7253 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7254 #endif 7255 } else if (isTetgen) { 7256 #ifdef PETSC_HAVE_TETGEN 7257 double *maxVolumes; 7258 PetscInt c; 7259 7260 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7261 for (c = 0; c < cEnd-cStart; ++c) { 7262 maxVolumes[c] = refinementLimit; 7263 } 7264 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7265 #else 7266 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7267 #endif 7268 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7269 break; 7270 default: 7271 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7272 } 7273 PetscFunctionReturn(0); 7274 } 7275 7276 #undef __FUNCT__ 7277 #define __FUNCT__ "DMPlexGetDepth" 7278 /*@ 7279 DMPlexGetDepth - get the number of strata 7280 7281 Not Collective 7282 7283 Input Parameters: 7284 . dm - The DMPlex object 7285 7286 Output Parameters: 7287 . depth - number of strata 7288 7289 Level: developer 7290 7291 Notes: 7292 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7293 7294 .keywords: mesh, points 7295 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7296 @*/ 7297 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7298 { 7299 PetscInt d; 7300 PetscErrorCode ierr; 7301 7302 PetscFunctionBegin; 7303 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7304 PetscValidPointer(depth, 2); 7305 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7306 *depth = d-1; 7307 PetscFunctionReturn(0); 7308 } 7309 7310 #undef __FUNCT__ 7311 #define __FUNCT__ "DMPlexGetDepthStratum" 7312 /*@ 7313 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7314 7315 Not Collective 7316 7317 Input Parameters: 7318 + dm - The DMPlex object 7319 - stratumValue - The requested depth 7320 7321 Output Parameters: 7322 + start - The first point at this depth 7323 - end - One beyond the last point at this depth 7324 7325 Level: developer 7326 7327 .keywords: mesh, points 7328 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7329 @*/ 7330 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) { 7331 DM_Plex *mesh = (DM_Plex *) dm->data; 7332 DMLabel next = mesh->labels; 7333 PetscBool flg = PETSC_FALSE; 7334 PetscInt depth; 7335 PetscErrorCode ierr; 7336 7337 PetscFunctionBegin; 7338 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7339 if (stratumValue < 0) { 7340 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7341 PetscFunctionReturn(0); 7342 } else { 7343 PetscInt pStart, pEnd; 7344 7345 if (start) {*start = 0;} 7346 if (end) {*end = 0;} 7347 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7348 if (pStart == pEnd) {PetscFunctionReturn(0);} 7349 } 7350 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7351 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7352 /* We should have a generic GetLabel() and a Label class */ 7353 while(next) { 7354 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7355 if (flg) break; 7356 next = next->next; 7357 } 7358 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7359 depth = stratumValue; 7360 if ((depth < 0) || (depth >= next->numStrata)) { 7361 if (start) {*start = 0;} 7362 if (end) {*end = 0;} 7363 } else { 7364 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7365 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7366 } 7367 PetscFunctionReturn(0); 7368 } 7369 7370 #undef __FUNCT__ 7371 #define __FUNCT__ "DMPlexGetHeightStratum" 7372 /*@ 7373 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7374 7375 Not Collective 7376 7377 Input Parameters: 7378 + dm - The DMPlex object 7379 - stratumValue - The requested height 7380 7381 Output Parameters: 7382 + start - The first point at this height 7383 - end - One beyond the last point at this height 7384 7385 Level: developer 7386 7387 .keywords: mesh, points 7388 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7389 @*/ 7390 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) { 7391 DM_Plex *mesh = (DM_Plex *) dm->data; 7392 DMLabel next = mesh->labels; 7393 PetscBool flg = PETSC_FALSE; 7394 PetscInt depth; 7395 PetscErrorCode ierr; 7396 7397 PetscFunctionBegin; 7398 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7399 if (stratumValue < 0) { 7400 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7401 } else { 7402 PetscInt pStart, pEnd; 7403 7404 if (start) {*start = 0;} 7405 if (end) {*end = 0;} 7406 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7407 if (pStart == pEnd) {PetscFunctionReturn(0);} 7408 } 7409 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7410 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7411 /* We should have a generic GetLabel() and a Label class */ 7412 while(next) { 7413 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7414 if (flg) break; 7415 next = next->next; 7416 } 7417 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7418 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7419 if ((depth < 0) || (depth >= next->numStrata)) { 7420 if (start) {*start = 0;} 7421 if (end) {*end = 0;} 7422 } else { 7423 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7424 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7425 } 7426 PetscFunctionReturn(0); 7427 } 7428 7429 #undef __FUNCT__ 7430 #define __FUNCT__ "DMPlexCreateSectionInitial" 7431 /* Set the number of dof on each point and separate by fields */ 7432 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) { 7433 PetscInt *numDofTot; 7434 PetscInt pStart = 0, pEnd = 0; 7435 PetscInt p, d, f; 7436 PetscErrorCode ierr; 7437 7438 PetscFunctionBegin; 7439 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7440 for(d = 0; d <= dim; ++d) { 7441 numDofTot[d] = 0; 7442 for(f = 0; f < numFields; ++f) { 7443 numDofTot[d] += numDof[f*(dim+1)+d]; 7444 } 7445 } 7446 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7447 if (numFields > 0) { 7448 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7449 if (numComp) { 7450 for(f = 0; f < numFields; ++f) { 7451 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7452 } 7453 } 7454 } 7455 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7456 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7457 for(d = 0; d <= dim; ++d) { 7458 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7459 for(p = pStart; p < pEnd; ++p) { 7460 for(f = 0; f < numFields; ++f) { 7461 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7462 } 7463 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7464 } 7465 } 7466 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7467 PetscFunctionReturn(0); 7468 } 7469 7470 #undef __FUNCT__ 7471 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7472 /* Set the number of dof on each point and separate by fields 7473 If constDof is PETSC_DETERMINE, constrain every dof on the point 7474 */ 7475 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) { 7476 PetscInt numFields; 7477 PetscInt bc; 7478 PetscErrorCode ierr; 7479 7480 PetscFunctionBegin; 7481 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7482 for (bc = 0; bc < numBC; ++bc) { 7483 PetscInt field = 0; 7484 const PetscInt *idx; 7485 PetscInt n, i; 7486 7487 if (numFields) {field = bcField[bc];} 7488 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7489 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7490 for (i = 0; i < n; ++i) { 7491 const PetscInt p = idx[i]; 7492 PetscInt numConst = constDof; 7493 7494 /* Constrain every dof on the point */ 7495 if (numConst < 0) { 7496 if (numFields) { 7497 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7498 } else { 7499 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7500 } 7501 } 7502 if (numFields) { 7503 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7504 } 7505 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7506 } 7507 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7508 } 7509 PetscFunctionReturn(0); 7510 } 7511 7512 #undef __FUNCT__ 7513 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7514 /* Set the constrained indices on each point and separate by fields */ 7515 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) { 7516 PetscInt *maxConstraints; 7517 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7518 PetscErrorCode ierr; 7519 7520 PetscFunctionBegin; 7521 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7522 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7523 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7524 for(f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 7525 for(p = pStart; p < pEnd; ++p) { 7526 PetscInt cdof; 7527 7528 if (numFields) { 7529 for(f = 0; f < numFields; ++f) { 7530 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7531 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7532 } 7533 } else { 7534 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7535 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7536 } 7537 } 7538 for (f = 0; f < numFields; ++f) { 7539 maxConstraints[numFields] += maxConstraints[f]; 7540 } 7541 if (maxConstraints[numFields]) { 7542 PetscInt *indices; 7543 7544 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7545 for (p = pStart; p < pEnd; ++p) { 7546 PetscInt cdof, d; 7547 7548 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7549 if (cdof) { 7550 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7551 if (numFields) { 7552 PetscInt numConst = 0, foff = 0; 7553 7554 for (f = 0; f < numFields; ++f) { 7555 PetscInt cfdof, fdof; 7556 7557 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7558 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7559 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7560 for(d = 0; d < cfdof; ++d) { 7561 indices[numConst+d] = d; 7562 } 7563 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7564 for(d = 0; d < cfdof; ++d) { 7565 indices[numConst+d] += foff; 7566 } 7567 numConst += cfdof; 7568 foff += fdof; 7569 } 7570 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7571 } else { 7572 for (d = 0; d < cdof; ++d) { 7573 indices[d] = d; 7574 } 7575 } 7576 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7577 } 7578 } 7579 ierr = PetscFree(indices);CHKERRQ(ierr); 7580 } 7581 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7582 PetscFunctionReturn(0); 7583 } 7584 7585 #undef __FUNCT__ 7586 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7587 /* Set the constrained field indices on each point */ 7588 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) { 7589 const PetscInt *points, *indices; 7590 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7591 PetscErrorCode ierr; 7592 7593 PetscFunctionBegin; 7594 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7595 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7596 7597 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7598 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7599 if (!constraintIndices) { 7600 PetscInt *idx, i; 7601 7602 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7603 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7604 for(i = 0; i < maxDof; ++i) {idx[i] = i;} 7605 for(p = 0; p < numPoints; ++p) { 7606 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7607 } 7608 ierr = PetscFree(idx);CHKERRQ(ierr); 7609 } else { 7610 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7611 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7612 for(p = 0; p < numPoints; ++p) { 7613 PetscInt fcdof; 7614 7615 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7616 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); 7617 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7618 } 7619 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7620 } 7621 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7622 PetscFunctionReturn(0); 7623 } 7624 7625 #undef __FUNCT__ 7626 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7627 /* Set the constrained indices on each point and separate by fields */ 7628 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) { 7629 PetscInt *indices; 7630 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7631 PetscErrorCode ierr; 7632 7633 PetscFunctionBegin; 7634 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7635 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7636 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7637 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7638 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7639 for (p = pStart; p < pEnd; ++p) { 7640 PetscInt cdof, d; 7641 7642 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7643 if (cdof) { 7644 PetscInt numConst = 0, foff = 0; 7645 7646 for (f = 0; f < numFields; ++f) { 7647 const PetscInt *fcind; 7648 PetscInt fdof, fcdof; 7649 7650 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7651 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7652 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7653 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7654 for(d = 0; d < fcdof; ++d) { 7655 indices[numConst+d] = fcind[d]+foff; 7656 } 7657 foff += fdof; 7658 numConst += fcdof; 7659 } 7660 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7661 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7662 } 7663 } 7664 ierr = PetscFree(indices);CHKERRQ(ierr); 7665 PetscFunctionReturn(0); 7666 } 7667 7668 #undef __FUNCT__ 7669 #define __FUNCT__ "DMPlexCreateSection" 7670 /*@C 7671 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7672 7673 Not Collective 7674 7675 Input Parameters: 7676 + dm - The DMPlex object 7677 . dim - The spatial dimension of the problem 7678 . numFields - The number of fields in the problem 7679 . numComp - An array of size numFields that holds the number of components for each field 7680 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7681 . numBC - The number of boundary conditions 7682 . bcField - An array of size numBC giving the field number for each boundry condition 7683 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7684 7685 Output Parameter: 7686 . section - The PetscSection object 7687 7688 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 7689 nubmer of dof for field 0 on each edge. 7690 7691 Level: developer 7692 7693 .keywords: mesh, elements 7694 .seealso: DMPlexCreate(), PetscSectionCreate() 7695 @*/ 7696 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) { 7697 PetscErrorCode ierr; 7698 7699 PetscFunctionBegin; 7700 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7701 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7702 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7703 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7704 { 7705 PetscBool view = PETSC_FALSE; 7706 7707 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7708 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7709 } 7710 PetscFunctionReturn(0); 7711 } 7712 7713 #undef __FUNCT__ 7714 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7715 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) { 7716 PetscSection section; 7717 PetscErrorCode ierr; 7718 7719 PetscFunctionBegin; 7720 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7721 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 7722 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7723 PetscFunctionReturn(0); 7724 } 7725 7726 #undef __FUNCT__ 7727 #define __FUNCT__ "DMPlexGetCoordinateSection" 7728 /*@ 7729 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7730 7731 Not Collective 7732 7733 Input Parameter: 7734 . dm - The DMPlex object 7735 7736 Output Parameter: 7737 . section - The PetscSection object 7738 7739 Level: intermediate 7740 7741 .keywords: mesh, coordinates 7742 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7743 @*/ 7744 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) { 7745 DM cdm; 7746 PetscErrorCode ierr; 7747 7748 PetscFunctionBegin; 7749 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7750 PetscValidPointer(section, 2); 7751 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7752 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7753 PetscFunctionReturn(0); 7754 } 7755 7756 #undef __FUNCT__ 7757 #define __FUNCT__ "DMPlexSetCoordinateSection" 7758 /*@ 7759 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7760 7761 Not Collective 7762 7763 Input Parameters: 7764 + dm - The DMPlex object 7765 - section - The PetscSection object 7766 7767 Level: intermediate 7768 7769 .keywords: mesh, coordinates 7770 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7771 @*/ 7772 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) { 7773 DM cdm; 7774 PetscErrorCode ierr; 7775 7776 PetscFunctionBegin; 7777 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7778 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7779 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7780 PetscFunctionReturn(0); 7781 } 7782 7783 #undef __FUNCT__ 7784 #define __FUNCT__ "DMPlexGetConeSection" 7785 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) { 7786 DM_Plex *mesh = (DM_Plex *) dm->data; 7787 7788 PetscFunctionBegin; 7789 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7790 if (section) *section = mesh->coneSection; 7791 PetscFunctionReturn(0); 7792 } 7793 7794 #undef __FUNCT__ 7795 #define __FUNCT__ "DMPlexGetCones" 7796 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) { 7797 DM_Plex *mesh = (DM_Plex *) dm->data; 7798 7799 PetscFunctionBegin; 7800 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7801 if (cones) *cones = mesh->cones; 7802 PetscFunctionReturn(0); 7803 } 7804 7805 #undef __FUNCT__ 7806 #define __FUNCT__ "DMPlexGetConeOrientations" 7807 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) { 7808 DM_Plex *mesh = (DM_Plex *) dm->data; 7809 7810 PetscFunctionBegin; 7811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7812 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7813 PetscFunctionReturn(0); 7814 } 7815 7816 #undef __FUNCT__ 7817 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7818 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7819 { 7820 const PetscInt embedDim = 2; 7821 PetscReal x = PetscRealPart(point[0]); 7822 PetscReal y = PetscRealPart(point[1]); 7823 PetscReal v0[2], J[4], invJ[4], detJ; 7824 PetscReal xi, eta; 7825 PetscErrorCode ierr; 7826 7827 PetscFunctionBegin; 7828 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7829 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7830 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7831 7832 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 7833 *cell = c; 7834 } else { 7835 *cell = -1; 7836 } 7837 PetscFunctionReturn(0); 7838 } 7839 7840 #undef __FUNCT__ 7841 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7842 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7843 { 7844 PetscSection coordSection; 7845 Vec coordsLocal; 7846 const PetscScalar *coords; 7847 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7848 PetscReal x = PetscRealPart(point[0]); 7849 PetscReal y = PetscRealPart(point[1]); 7850 PetscInt crossings = 0, f; 7851 PetscErrorCode ierr; 7852 7853 PetscFunctionBegin; 7854 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7855 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7856 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7857 for(f = 0; f < 4; ++f) { 7858 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7859 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7860 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7861 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7862 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7863 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7864 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7865 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7866 if ((cond1 || cond2) && above) ++crossings; 7867 } 7868 if (crossings % 2) { 7869 *cell = c; 7870 } else { 7871 *cell = -1; 7872 } 7873 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7874 PetscFunctionReturn(0); 7875 } 7876 7877 #undef __FUNCT__ 7878 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7879 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7880 { 7881 const PetscInt embedDim = 3; 7882 PetscReal v0[3], J[9], invJ[9], detJ; 7883 PetscReal x = PetscRealPart(point[0]); 7884 PetscReal y = PetscRealPart(point[1]); 7885 PetscReal z = PetscRealPart(point[2]); 7886 PetscReal xi, eta, zeta; 7887 PetscErrorCode ierr; 7888 7889 PetscFunctionBegin; 7890 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7891 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7892 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7893 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7894 7895 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 7896 *cell = c; 7897 } else { 7898 *cell = -1; 7899 } 7900 PetscFunctionReturn(0); 7901 } 7902 7903 #undef __FUNCT__ 7904 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7905 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7906 { 7907 PetscSection coordSection; 7908 Vec coordsLocal; 7909 const PetscScalar *coords; 7910 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7911 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7912 PetscBool found = PETSC_TRUE; 7913 PetscInt f; 7914 PetscErrorCode ierr; 7915 7916 PetscFunctionBegin; 7917 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7918 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7919 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7920 for(f = 0; f < 6; ++f) { 7921 /* Check the point is under plane */ 7922 /* Get face normal */ 7923 PetscReal v_i[3] = {PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]), 7924 PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]), 7925 PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2])}; 7926 PetscReal v_j[3] = {PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]), 7927 PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]), 7928 PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2])}; 7929 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]}; 7930 PetscReal pp[3] = {PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]), 7931 PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]), 7932 PetscRealPart(coords[faces[f*4+0]*3+2] - point[2])}; 7933 PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7934 /* Check that projected point is in face (2D location problem) */ 7935 if (dot < 0.0) { 7936 found = PETSC_FALSE; 7937 break; 7938 } 7939 } 7940 if (found) { 7941 *cell = c; 7942 } else { 7943 *cell = -1; 7944 } 7945 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7946 PetscFunctionReturn(0); 7947 } 7948 7949 #undef __FUNCT__ 7950 #define __FUNCT__ "DMLocatePoints_Plex" 7951 /* 7952 Need to implement using the guess 7953 */ 7954 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7955 { 7956 PetscInt cell = -1/*, guess = -1*/; 7957 PetscInt bs, numPoints, p; 7958 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7959 PetscInt *cells; 7960 PetscScalar *a; 7961 PetscErrorCode ierr; 7962 7963 PetscFunctionBegin; 7964 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7965 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7966 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7967 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 7968 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7969 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7970 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7971 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); 7972 numPoints /= bs; 7973 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7974 for(p = 0; p < numPoints; ++p) { 7975 const PetscScalar *point = &a[p*bs]; 7976 7977 switch(dim) { 7978 case 2: 7979 for(c = cStart; c < cEnd; ++c) { 7980 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7981 switch(coneSize) { 7982 case 3: 7983 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7984 break; 7985 case 4: 7986 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7987 break; 7988 default: 7989 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7990 } 7991 if (cell >= 0) break; 7992 } 7993 break; 7994 case 3: 7995 for(c = cStart; c < cEnd; ++c) { 7996 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7997 switch(coneSize) { 7998 case 4: 7999 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8000 break; 8001 case 8: 8002 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8003 break; 8004 default: 8005 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8006 } 8007 if (cell >= 0) break; 8008 } 8009 break; 8010 default: 8011 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8012 } 8013 cells[p] = cell; 8014 } 8015 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8016 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8017 PetscFunctionReturn(0); 8018 } 8019 8020 /******************************** FEM Support **********************************/ 8021 8022 #undef __FUNCT__ 8023 #define __FUNCT__ "DMPlexVecGetClosure" 8024 /*@C 8025 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8026 8027 Not collective 8028 8029 Input Parameters: 8030 + dm - The DM 8031 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8032 . v - The local vector 8033 - point - The sieve point in the DM 8034 8035 Output Parameters: 8036 + csize - The number of values in the closure, or PETSC_NULL 8037 - values - The array of values, which is a borrowed array and should not be freed 8038 8039 Level: intermediate 8040 8041 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8042 @*/ 8043 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 8044 PetscScalar *array, *vArray; 8045 PetscInt *points = PETSC_NULL; 8046 PetscInt offsets[32]; 8047 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8048 PetscErrorCode ierr; 8049 8050 PetscFunctionBegin; 8051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8052 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8053 if (!section) { 8054 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8055 } 8056 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8057 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8058 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8059 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8060 /* Compress out points not in the section */ 8061 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8062 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8063 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8064 points[q*2] = points[p]; 8065 points[q*2+1] = points[p+1]; 8066 ++q; 8067 } 8068 } 8069 numPoints = q; 8070 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8071 PetscInt dof, fdof; 8072 8073 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8074 for (f = 0; f < numFields; ++f) { 8075 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8076 offsets[f+1] += fdof; 8077 } 8078 size += dof; 8079 } 8080 for (f = 1; f < numFields; ++f) { 8081 offsets[f+1] += offsets[f]; 8082 } 8083 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8084 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8085 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8086 for (p = 0; p < numPoints*2; p += 2) { 8087 PetscInt o = points[p+1]; 8088 PetscInt dof, off, d; 8089 PetscScalar *varr; 8090 8091 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8092 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8093 varr = &vArray[off]; 8094 if (numFields) { 8095 PetscInt fdof, foff, fcomp, f, c; 8096 8097 for (f = 0, foff = 0; f < numFields; ++f) { 8098 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8099 if (o >= 0) { 8100 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8101 array[offsets[f]] = varr[foff+d]; 8102 } 8103 } else { 8104 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8105 for (d = fdof/fcomp-1; d >= 0; --d) { 8106 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8107 array[offsets[f]] = varr[foff+d*fcomp+c]; 8108 } 8109 } 8110 } 8111 foff += fdof; 8112 } 8113 } else { 8114 if (o >= 0) { 8115 for (d = 0; d < dof; ++d, ++offsets[0]) { 8116 array[offsets[0]] = varr[d]; 8117 } 8118 } else { 8119 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8120 array[offsets[0]] = varr[d]; 8121 } 8122 } 8123 } 8124 } 8125 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8126 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8127 if (csize) *csize = size; 8128 *values = array; 8129 PetscFunctionReturn(0); 8130 } 8131 8132 #undef __FUNCT__ 8133 #define __FUNCT__ "DMPlexVecRestoreClosure" 8134 /*@C 8135 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8136 8137 Not collective 8138 8139 Input Parameters: 8140 + dm - The DM 8141 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8142 . v - The local vector 8143 . point - The sieve point in the DM 8144 . csize - The number of values in the closure, or PETSC_NULL 8145 - values - The array of values, which is a borrowed array and should not be freed 8146 8147 Level: intermediate 8148 8149 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8150 @*/ 8151 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 8152 PetscInt size = 0; 8153 PetscErrorCode ierr; 8154 8155 PetscFunctionBegin; 8156 /* Should work without recalculating size */ 8157 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 8158 PetscFunctionReturn(0); 8159 } 8160 8161 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8162 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8163 8164 #undef __FUNCT__ 8165 #define __FUNCT__ "updatePoint_private" 8166 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8167 { 8168 PetscInt cdof; /* The number of constraints on this point */ 8169 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8170 PetscScalar *a; 8171 PetscInt off, cind = 0, k; 8172 PetscErrorCode ierr; 8173 8174 PetscFunctionBegin; 8175 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8176 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8177 a = &array[off]; 8178 if (!cdof || setBC) { 8179 if (orientation >= 0) { 8180 for (k = 0; k < dof; ++k) { 8181 fuse(&a[k], values[k]); 8182 } 8183 } else { 8184 for (k = 0; k < dof; ++k) { 8185 fuse(&a[k], values[dof-k-1]); 8186 } 8187 } 8188 } else { 8189 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8190 if (orientation >= 0) { 8191 for (k = 0; k < dof; ++k) { 8192 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8193 fuse(&a[k], values[k]); 8194 } 8195 } else { 8196 for (k = 0; k < dof; ++k) { 8197 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8198 fuse(&a[k], values[dof-k-1]); 8199 } 8200 } 8201 } 8202 PetscFunctionReturn(0); 8203 } 8204 8205 #undef __FUNCT__ 8206 #define __FUNCT__ "updatePointFields_private" 8207 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) { 8208 PetscScalar *a; 8209 PetscInt numFields, off, foff, f; 8210 PetscErrorCode ierr; 8211 8212 PetscFunctionBegin; 8213 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8214 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8215 a = &array[off]; 8216 for (f = 0, foff = 0; f < numFields; ++f) { 8217 PetscInt fdof, fcomp, fcdof; 8218 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8219 PetscInt cind = 0, k, c; 8220 8221 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8222 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8223 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8224 if (!fcdof || setBC) { 8225 if (orientation >= 0) { 8226 for (k = 0; k < fdof; ++k) { 8227 fuse(&a[foff+k], values[foffs[f]+k]); 8228 } 8229 } else { 8230 for (k = fdof/fcomp-1; k >= 0; --k) { 8231 for (c = 0; c < fcomp; ++c) { 8232 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8233 } 8234 } 8235 } 8236 } else { 8237 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8238 if (orientation >= 0) { 8239 for (k = 0; k < fdof; ++k) { 8240 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8241 fuse(&a[foff+k], values[foffs[f]+k]); 8242 } 8243 } else { 8244 for (k = fdof/fcomp-1; k >= 0; --k) { 8245 for (c = 0; c < fcomp; ++c) { 8246 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8247 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8248 } 8249 } 8250 } 8251 } 8252 foff += fdof; 8253 foffs[f] += fdof; 8254 } 8255 PetscFunctionReturn(0); 8256 } 8257 8258 #undef __FUNCT__ 8259 #define __FUNCT__ "DMPlexVecSetClosure" 8260 /*@C 8261 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8262 8263 Not collective 8264 8265 Input Parameters: 8266 + dm - The DM 8267 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8268 . v - The local vector 8269 . point - The sieve point in the DM 8270 . values - The array of values, which is a borrowed array and should not be freed 8271 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8272 8273 Level: intermediate 8274 8275 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8276 @*/ 8277 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) { 8278 PetscScalar *array; 8279 PetscInt *points = PETSC_NULL; 8280 PetscInt offsets[32]; 8281 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8282 PetscErrorCode ierr; 8283 8284 PetscFunctionBegin; 8285 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8286 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8287 if (!section) { 8288 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8289 } 8290 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8291 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8292 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8293 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8294 /* Compress out points not in the section */ 8295 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8296 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8297 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8298 points[q*2] = points[p]; 8299 points[q*2+1] = points[p+1]; 8300 ++q; 8301 } 8302 } 8303 numPoints = q; 8304 for (p = 0; p < numPoints*2; p += 2) { 8305 PetscInt fdof; 8306 8307 for (f = 0; f < numFields; ++f) { 8308 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8309 offsets[f+1] += fdof; 8310 } 8311 } 8312 for (f = 1; f < numFields; ++f) { 8313 offsets[f+1] += offsets[f]; 8314 } 8315 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8316 if (numFields) { 8317 switch(mode) { 8318 case INSERT_VALUES: 8319 for (p = 0; p < numPoints*2; p += 2) { 8320 PetscInt o = points[p+1]; 8321 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8322 } break; 8323 case INSERT_ALL_VALUES: 8324 for (p = 0; p < numPoints*2; p += 2) { 8325 PetscInt o = points[p+1]; 8326 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8327 } break; 8328 case ADD_VALUES: 8329 for (p = 0; p < numPoints*2; p += 2) { 8330 PetscInt o = points[p+1]; 8331 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8332 } break; 8333 case ADD_ALL_VALUES: 8334 for (p = 0; p < numPoints*2; p += 2) { 8335 PetscInt o = points[p+1]; 8336 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8337 } break; 8338 default: 8339 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8340 } 8341 } else { 8342 switch(mode) { 8343 case INSERT_VALUES: 8344 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8345 PetscInt o = points[p+1]; 8346 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8347 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8348 } break; 8349 case INSERT_ALL_VALUES: 8350 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8351 PetscInt o = points[p+1]; 8352 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8353 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8354 } break; 8355 case ADD_VALUES: 8356 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8357 PetscInt o = points[p+1]; 8358 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8359 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8360 } break; 8361 case ADD_ALL_VALUES: 8362 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8363 PetscInt o = points[p+1]; 8364 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8365 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8366 } break; 8367 default: 8368 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8369 } 8370 } 8371 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8372 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8373 PetscFunctionReturn(0); 8374 } 8375 8376 #undef __FUNCT__ 8377 #define __FUNCT__ "DMPlexPrintMatSetValues" 8378 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8379 { 8380 PetscMPIInt rank; 8381 PetscInt i, j; 8382 PetscErrorCode ierr; 8383 8384 PetscFunctionBegin; 8385 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8386 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8387 for (i = 0; i < numIndices; i++) { 8388 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8389 } 8390 for (i = 0; i < numIndices; i++) { 8391 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8392 for (j = 0; j < numIndices; j++) { 8393 #ifdef PETSC_USE_COMPLEX 8394 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8395 #else 8396 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8397 #endif 8398 } 8399 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8400 } 8401 PetscFunctionReturn(0); 8402 } 8403 8404 #undef __FUNCT__ 8405 #define __FUNCT__ "indicesPoint_private" 8406 /* . off - The global offset of this point */ 8407 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 8408 PetscInt cdof; /* The number of constraints on this point */ 8409 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8410 PetscInt cind = 0, k; 8411 PetscErrorCode ierr; 8412 8413 PetscFunctionBegin; 8414 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8415 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8416 if (!cdof || setBC) { 8417 if (orientation >= 0) { 8418 for (k = 0; k < dof; ++k) { 8419 indices[k] = off+k; 8420 } 8421 } else { 8422 for (k = 0; k < dof; ++k) { 8423 indices[dof-k-1] = off+k; 8424 } 8425 } 8426 } else { 8427 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8428 if (orientation >= 0) { 8429 for (k = 0; k < dof; ++k) { 8430 if ((cind < cdof) && (k == cdofs[cind])) { 8431 /* Insert check for returning constrained indices */ 8432 indices[k] = -(off+k+1); 8433 ++cind; 8434 } else { 8435 indices[k] = off+k-cind; 8436 } 8437 } 8438 } else { 8439 for (k = 0; k < dof; ++k) { 8440 if ((cind < cdof) && (k == cdofs[cind])) { 8441 /* Insert check for returning constrained indices */ 8442 indices[dof-k-1] = -(off+k+1); 8443 ++cind; 8444 } else { 8445 indices[dof-k-1] = off+k-cind; 8446 } 8447 } 8448 } 8449 } 8450 PetscFunctionReturn(0); 8451 } 8452 8453 #undef __FUNCT__ 8454 #define __FUNCT__ "indicesPointFields_private" 8455 /* . off - The global offset of this point */ 8456 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 8457 PetscInt numFields, foff, f; 8458 PetscErrorCode ierr; 8459 8460 PetscFunctionBegin; 8461 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8462 for (f = 0, foff = 0; f < numFields; ++f) { 8463 PetscInt fdof, fcomp, cfdof; 8464 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8465 PetscInt cind = 0, k, c; 8466 8467 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8468 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8469 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8470 if (!cfdof || setBC) { 8471 if (orientation >= 0) { 8472 for (k = 0; k < fdof; ++k) { 8473 indices[foffs[f]+k] = off+foff+k; 8474 } 8475 } else { 8476 for (k = fdof/fcomp-1; k >= 0; --k) { 8477 for (c = 0; c < fcomp; ++c) { 8478 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8479 } 8480 } 8481 } 8482 } else { 8483 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8484 if (orientation >= 0) { 8485 for (k = 0; k < fdof; ++k) { 8486 if ((cind < cfdof) && (k == fcdofs[cind])) { 8487 indices[foffs[f]+k] = -(off+foff+k+1); 8488 ++cind; 8489 } else { 8490 indices[foffs[f]+k] = off+foff+k-cind; 8491 } 8492 } 8493 } else { 8494 for (k = fdof/fcomp-1; k >= 0; --k) { 8495 for (c = 0; c < fcomp; ++c) { 8496 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8497 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8498 ++cind; 8499 } else { 8500 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8501 } 8502 } 8503 } 8504 } 8505 } 8506 foff += fdof - cfdof; 8507 foffs[f] += fdof; 8508 } 8509 PetscFunctionReturn(0); 8510 } 8511 8512 #undef __FUNCT__ 8513 #define __FUNCT__ "DMPlexMatSetClosure" 8514 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8515 { 8516 DM_Plex *mesh = (DM_Plex *) dm->data; 8517 PetscInt *points = PETSC_NULL; 8518 PetscInt *indices; 8519 PetscInt offsets[32]; 8520 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8521 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8522 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8523 PetscErrorCode ierr; 8524 8525 PetscFunctionBegin; 8526 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8527 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8528 if (useDefault) { 8529 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8530 } 8531 if (useGlobalDefault) { 8532 if (useDefault) { 8533 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8534 } else { 8535 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8536 } 8537 } 8538 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8539 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8540 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8541 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8542 /* Compress out points not in the section */ 8543 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8544 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8545 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8546 points[q*2] = points[p]; 8547 points[q*2+1] = points[p+1]; 8548 ++q; 8549 } 8550 } 8551 numPoints = q; 8552 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8553 PetscInt fdof; 8554 8555 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8556 for (f = 0; f < numFields; ++f) { 8557 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8558 offsets[f+1] += fdof; 8559 } 8560 numIndices += dof; 8561 } 8562 for (f = 1; f < numFields; ++f) { 8563 offsets[f+1] += offsets[f]; 8564 } 8565 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8566 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8567 if (numFields) { 8568 for (p = 0; p < numPoints*2; p += 2) { 8569 PetscInt o = points[p+1]; 8570 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8571 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8572 } 8573 } else { 8574 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8575 PetscInt o = points[p+1]; 8576 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8577 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8578 } 8579 } 8580 if (useGlobalDefault && !useDefault) { 8581 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8582 } 8583 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8584 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8585 if (ierr) { 8586 PetscMPIInt rank; 8587 PetscErrorCode ierr2; 8588 8589 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8590 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8591 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8592 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8593 CHKERRQ(ierr); 8594 } 8595 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8596 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8597 PetscFunctionReturn(0); 8598 } 8599 8600 #undef __FUNCT__ 8601 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8602 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8603 { 8604 PetscSection coordSection; 8605 Vec coordinates; 8606 const PetscScalar *coords; 8607 const PetscInt dim = 2; 8608 PetscInt d, f; 8609 PetscErrorCode ierr; 8610 8611 PetscFunctionBegin; 8612 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8613 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8614 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8615 if (v0) { 8616 for (d = 0; d < dim; d++) { 8617 v0[d] = PetscRealPart(coords[d]); 8618 } 8619 } 8620 if (J) { 8621 for (d = 0; d < dim; d++) { 8622 for (f = 0; f < dim; f++) { 8623 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8624 } 8625 } 8626 *detJ = J[0]*J[3] - J[1]*J[2]; 8627 #if 0 8628 if (detJ < 0.0) { 8629 const PetscReal xLength = mesh->periodicity[0]; 8630 8631 if (xLength != 0.0) { 8632 PetscReal v0x = coords[0*dim+0]; 8633 8634 if (v0x == 0.0) { 8635 v0x = v0[0] = xLength; 8636 } 8637 for (f = 0; f < dim; f++) { 8638 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8639 8640 J[0*dim+f] = 0.5*(px - v0x); 8641 } 8642 } 8643 detJ = J[0]*J[3] - J[1]*J[2]; 8644 } 8645 #endif 8646 PetscLogFlops(8.0 + 3.0); 8647 } 8648 if (invJ) { 8649 const PetscReal invDet = 1.0/(*detJ); 8650 8651 invJ[0] = invDet*J[3]; 8652 invJ[1] = -invDet*J[1]; 8653 invJ[2] = -invDet*J[2]; 8654 invJ[3] = invDet*J[0]; 8655 PetscLogFlops(5.0); 8656 } 8657 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8658 PetscFunctionReturn(0); 8659 } 8660 8661 #undef __FUNCT__ 8662 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8663 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8664 { 8665 PetscSection coordSection; 8666 Vec coordinates; 8667 const PetscScalar *coords; 8668 const PetscInt dim = 2; 8669 PetscInt d, f; 8670 PetscErrorCode ierr; 8671 8672 PetscFunctionBegin; 8673 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8674 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8675 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8676 if (v0) { 8677 for (d = 0; d < dim; d++) { 8678 v0[d] = PetscRealPart(coords[d]); 8679 } 8680 } 8681 if (J) { 8682 for (d = 0; d < dim; d++) { 8683 for (f = 0; f < dim; f++) { 8684 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8685 } 8686 } 8687 *detJ = J[0]*J[3] - J[1]*J[2]; 8688 PetscLogFlops(8.0 + 3.0); 8689 } 8690 if (invJ) { 8691 const PetscReal invDet = 1.0/(*detJ); 8692 8693 invJ[0] = invDet*J[3]; 8694 invJ[1] = -invDet*J[1]; 8695 invJ[2] = -invDet*J[2]; 8696 invJ[3] = invDet*J[0]; 8697 PetscLogFlops(5.0); 8698 } 8699 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8700 PetscFunctionReturn(0); 8701 } 8702 8703 #undef __FUNCT__ 8704 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8705 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8706 { 8707 PetscSection coordSection; 8708 Vec coordinates; 8709 const PetscScalar *coords; 8710 const PetscInt dim = 3; 8711 PetscInt d, f; 8712 PetscErrorCode ierr; 8713 8714 PetscFunctionBegin; 8715 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8716 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8717 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8718 if (v0) { 8719 for (d = 0; d < dim; d++) { 8720 v0[d] = PetscRealPart(coords[d]); 8721 } 8722 } 8723 if (J) { 8724 for (d = 0; d < dim; d++) { 8725 for (f = 0; f < dim; f++) { 8726 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8727 } 8728 } 8729 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8730 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8731 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8732 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8733 PetscLogFlops(18.0 + 12.0); 8734 } 8735 if (invJ) { 8736 const PetscReal invDet = 1.0/(*detJ); 8737 8738 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8739 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8740 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8741 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8742 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8743 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8744 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8745 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8746 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8747 PetscLogFlops(37.0); 8748 } 8749 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8750 PetscFunctionReturn(0); 8751 } 8752 8753 #undef __FUNCT__ 8754 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8755 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8756 { 8757 PetscSection coordSection; 8758 Vec coordinates; 8759 const PetscScalar *coords; 8760 const PetscInt dim = 3; 8761 PetscInt d; 8762 PetscErrorCode ierr; 8763 8764 PetscFunctionBegin; 8765 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8766 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8767 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8768 if (v0) { 8769 for (d = 0; d < dim; d++) { 8770 v0[d] = PetscRealPart(coords[d]); 8771 } 8772 } 8773 if (J) { 8774 for (d = 0; d < dim; d++) { 8775 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8776 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8777 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8778 } 8779 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8780 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8781 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8782 PetscLogFlops(18.0 + 12.0); 8783 } 8784 if (invJ) { 8785 const PetscReal invDet = -1.0/(*detJ); 8786 8787 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8788 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8789 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8790 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8791 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8792 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8793 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8794 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8795 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8796 PetscLogFlops(37.0); 8797 } 8798 *detJ *= 8.0; 8799 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8800 PetscFunctionReturn(0); 8801 } 8802 8803 #undef __FUNCT__ 8804 #define __FUNCT__ "DMPlexComputeCellGeometry" 8805 /*@C 8806 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8807 8808 Collective on DM 8809 8810 Input Arguments: 8811 + dm - the DM 8812 - cell - the cell 8813 8814 Output Arguments: 8815 + v0 - the translation part of this affine transform 8816 . J - the Jacobian of the transform to the reference element 8817 . invJ - the inverse of the Jacobian 8818 - detJ - the Jacobian determinant 8819 8820 Level: advanced 8821 8822 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8823 @*/ 8824 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) { 8825 PetscInt dim, coneSize; 8826 PetscErrorCode ierr; 8827 8828 PetscFunctionBegin; 8829 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8830 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8831 switch(dim) { 8832 case 2: 8833 switch(coneSize) { 8834 case 3: 8835 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8836 break; 8837 case 4: 8838 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8839 break; 8840 default: 8841 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8842 } 8843 break; 8844 case 3: 8845 switch(coneSize) { 8846 case 4: 8847 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8848 break; 8849 case 8: 8850 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8851 break; 8852 default: 8853 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8854 } 8855 break; 8856 default: 8857 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8858 } 8859 PetscFunctionReturn(0); 8860 } 8861 8862 #undef __FUNCT__ 8863 #define __FUNCT__ "DMPlexGetFaceOrientation" 8864 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) { 8865 MPI_Comm comm = ((PetscObject) dm)->comm; 8866 PetscBool posOrient = PETSC_FALSE; 8867 const PetscInt debug = 0; 8868 PetscInt cellDim, faceSize, f; 8869 PetscErrorCode ierr; 8870 8871 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 8872 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 8873 8874 if (cellDim == numCorners-1) { 8875 /* Simplices */ 8876 faceSize = numCorners-1; 8877 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 8878 } else if (cellDim == 1 && numCorners == 3) { 8879 /* Quadratic line */ 8880 faceSize = 1; 8881 posOrient = PETSC_TRUE; 8882 } else if (cellDim == 2 && numCorners == 4) { 8883 /* Quads */ 8884 faceSize = 2; 8885 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 8886 posOrient = PETSC_TRUE; 8887 } else if ((indices[0] == 3) && (indices[1] == 0)) { 8888 posOrient = PETSC_TRUE; 8889 } else { 8890 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 8891 posOrient = PETSC_FALSE; 8892 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 8893 } 8894 } else if (cellDim == 2 && numCorners == 6) { 8895 /* Quadratic triangle (I hate this) */ 8896 /* Edges are determined by the first 2 vertices (corners of edges) */ 8897 const PetscInt faceSizeTri = 3; 8898 PetscInt sortedIndices[3], i, iFace; 8899 PetscBool found = PETSC_FALSE; 8900 PetscInt faceVerticesTriSorted[9] = { 8901 0, 3, 4, /* bottom */ 8902 1, 4, 5, /* right */ 8903 2, 3, 5, /* left */ 8904 }; 8905 PetscInt faceVerticesTri[9] = { 8906 0, 3, 4, /* bottom */ 8907 1, 4, 5, /* right */ 8908 2, 5, 3, /* left */ 8909 }; 8910 8911 faceSize = faceSizeTri; 8912 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 8913 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 8914 for (iFace = 0; iFace < 3; ++iFace) { 8915 const PetscInt ii = iFace*faceSizeTri; 8916 PetscInt fVertex, cVertex; 8917 8918 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 8919 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 8920 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 8921 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 8922 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 8923 faceVertices[fVertex] = origVertices[cVertex]; 8924 break; 8925 } 8926 } 8927 } 8928 found = PETSC_TRUE; 8929 break; 8930 } 8931 } 8932 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 8933 if (posOriented) {*posOriented = PETSC_TRUE;} 8934 PetscFunctionReturn(0); 8935 } else if (cellDim == 2 && numCorners == 9) { 8936 /* Quadratic quad (I hate this) */ 8937 /* Edges are determined by the first 2 vertices (corners of edges) */ 8938 const PetscInt faceSizeQuad = 3; 8939 PetscInt sortedIndices[3], i, iFace; 8940 PetscBool found = PETSC_FALSE; 8941 PetscInt faceVerticesQuadSorted[12] = { 8942 0, 1, 4, /* bottom */ 8943 1, 2, 5, /* right */ 8944 2, 3, 6, /* top */ 8945 0, 3, 7, /* left */ 8946 }; 8947 PetscInt faceVerticesQuad[12] = { 8948 0, 1, 4, /* bottom */ 8949 1, 2, 5, /* right */ 8950 2, 3, 6, /* top */ 8951 3, 0, 7, /* left */ 8952 }; 8953 8954 faceSize = faceSizeQuad; 8955 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 8956 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 8957 for (iFace = 0; iFace < 4; ++iFace) { 8958 const PetscInt ii = iFace*faceSizeQuad; 8959 PetscInt fVertex, cVertex; 8960 8961 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 8962 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 8963 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 8964 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 8965 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 8966 faceVertices[fVertex] = origVertices[cVertex]; 8967 break; 8968 } 8969 } 8970 } 8971 found = PETSC_TRUE; 8972 break; 8973 } 8974 } 8975 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 8976 if (posOriented) {*posOriented = PETSC_TRUE;} 8977 PetscFunctionReturn(0); 8978 } else if (cellDim == 3 && numCorners == 8) { 8979 /* Hexes 8980 A hex is two oriented quads with the normal of the first 8981 pointing up at the second. 8982 8983 7---6 8984 /| /| 8985 4---5 | 8986 | 3-|-2 8987 |/ |/ 8988 0---1 8989 8990 Faces are determined by the first 4 vertices (corners of faces) */ 8991 const PetscInt faceSizeHex = 4; 8992 PetscInt sortedIndices[4], i, iFace; 8993 PetscBool found = PETSC_FALSE; 8994 PetscInt faceVerticesHexSorted[24] = { 8995 0, 1, 2, 3, /* bottom */ 8996 4, 5, 6, 7, /* top */ 8997 0, 1, 4, 5, /* front */ 8998 1, 2, 5, 6, /* right */ 8999 2, 3, 6, 7, /* back */ 9000 0, 3, 4, 7, /* left */ 9001 }; 9002 PetscInt faceVerticesHex[24] = { 9003 3, 2, 1, 0, /* bottom */ 9004 4, 5, 6, 7, /* top */ 9005 0, 1, 5, 4, /* front */ 9006 1, 2, 6, 5, /* right */ 9007 2, 3, 7, 6, /* back */ 9008 3, 0, 4, 7, /* left */ 9009 }; 9010 9011 faceSize = faceSizeHex; 9012 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9013 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9014 for (iFace = 0; iFace < 6; ++iFace) { 9015 const PetscInt ii = iFace*faceSizeHex; 9016 PetscInt fVertex, cVertex; 9017 9018 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9019 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9020 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9021 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9022 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9023 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9024 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9025 faceVertices[fVertex] = origVertices[cVertex]; 9026 break; 9027 } 9028 } 9029 } 9030 found = PETSC_TRUE; 9031 break; 9032 } 9033 } 9034 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9035 if (posOriented) {*posOriented = PETSC_TRUE;} 9036 PetscFunctionReturn(0); 9037 } else if (cellDim == 3 && numCorners == 10) { 9038 /* Quadratic tet */ 9039 /* Faces are determined by the first 3 vertices (corners of faces) */ 9040 const PetscInt faceSizeTet = 6; 9041 PetscInt sortedIndices[6], i, iFace; 9042 PetscBool found = PETSC_FALSE; 9043 PetscInt faceVerticesTetSorted[24] = { 9044 0, 1, 2, 6, 7, 8, /* bottom */ 9045 0, 3, 4, 6, 7, 9, /* front */ 9046 1, 4, 5, 7, 8, 9, /* right */ 9047 2, 3, 5, 6, 8, 9, /* left */ 9048 }; 9049 PetscInt faceVerticesTet[24] = { 9050 0, 1, 2, 6, 7, 8, /* bottom */ 9051 0, 4, 3, 6, 7, 9, /* front */ 9052 1, 5, 4, 7, 8, 9, /* right */ 9053 2, 3, 5, 8, 6, 9, /* left */ 9054 }; 9055 9056 faceSize = faceSizeTet; 9057 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9058 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9059 for (iFace=0; iFace < 4; ++iFace) { 9060 const PetscInt ii = iFace*faceSizeTet; 9061 PetscInt fVertex, cVertex; 9062 9063 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9064 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9065 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9066 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9067 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9068 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9069 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9070 faceVertices[fVertex] = origVertices[cVertex]; 9071 break; 9072 } 9073 } 9074 } 9075 found = PETSC_TRUE; 9076 break; 9077 } 9078 } 9079 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9080 if (posOriented) {*posOriented = PETSC_TRUE;} 9081 PetscFunctionReturn(0); 9082 } else if (cellDim == 3 && numCorners == 27) { 9083 /* Quadratic hexes (I hate this) 9084 A hex is two oriented quads with the normal of the first 9085 pointing up at the second. 9086 9087 7---6 9088 /| /| 9089 4---5 | 9090 | 3-|-2 9091 |/ |/ 9092 0---1 9093 9094 Faces are determined by the first 4 vertices (corners of faces) */ 9095 const PetscInt faceSizeQuadHex = 9; 9096 PetscInt sortedIndices[9], i, iFace; 9097 PetscBool found = PETSC_FALSE; 9098 PetscInt faceVerticesQuadHexSorted[54] = { 9099 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9100 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9101 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9102 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9103 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9104 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9105 }; 9106 PetscInt faceVerticesQuadHex[54] = { 9107 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9108 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9109 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9110 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9111 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9112 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9113 }; 9114 9115 faceSize = faceSizeQuadHex; 9116 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9117 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9118 for (iFace = 0; iFace < 6; ++iFace) { 9119 const PetscInt ii = iFace*faceSizeQuadHex; 9120 PetscInt fVertex, cVertex; 9121 9122 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9123 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9124 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9125 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9126 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9127 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9128 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9129 faceVertices[fVertex] = origVertices[cVertex]; 9130 break; 9131 } 9132 } 9133 } 9134 found = PETSC_TRUE; 9135 break; 9136 } 9137 } 9138 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9139 if (posOriented) {*posOriented = PETSC_TRUE;} 9140 PetscFunctionReturn(0); 9141 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9142 if (!posOrient) { 9143 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9144 for (f = 0; f < faceSize; ++f) { 9145 faceVertices[f] = origVertices[faceSize-1 - f]; 9146 } 9147 } else { 9148 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9149 for (f = 0; f < faceSize; ++f) { 9150 faceVertices[f] = origVertices[f]; 9151 } 9152 } 9153 if (posOriented) {*posOriented = posOrient;} 9154 PetscFunctionReturn(0); 9155 } 9156 9157 #undef __FUNCT__ 9158 #define __FUNCT__ "DMPlexGetOrientedFace" 9159 /* 9160 Given a cell and a face, as a set of vertices, 9161 return the oriented face, as a set of vertices, in faceVertices 9162 The orientation is such that the face normal points out of the cell 9163 */ 9164 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9165 { 9166 const PetscInt *cone = PETSC_NULL; 9167 PetscInt coneSize, v, f, v2; 9168 PetscInt oppositeVertex = -1; 9169 PetscErrorCode ierr; 9170 9171 PetscFunctionBegin; 9172 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9173 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9174 for (v = 0, v2 = 0; v < coneSize; ++v) { 9175 PetscBool found = PETSC_FALSE; 9176 9177 for (f = 0; f < faceSize; ++f) { 9178 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 9179 } 9180 if (found) { 9181 indices[v2] = v; 9182 origVertices[v2] = cone[v]; 9183 ++v2; 9184 } else { 9185 oppositeVertex = v; 9186 } 9187 } 9188 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9189 PetscFunctionReturn(0); 9190 } 9191 9192 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9193 { 9194 switch(i) { 9195 case 0: 9196 switch(j) { 9197 case 0: return 0; 9198 case 1: 9199 switch(k) { 9200 case 0: return 0; 9201 case 1: return 0; 9202 case 2: return 1; 9203 } 9204 case 2: 9205 switch(k) { 9206 case 0: return 0; 9207 case 1: return -1; 9208 case 2: return 0; 9209 } 9210 } 9211 case 1: 9212 switch(j) { 9213 case 0: 9214 switch(k) { 9215 case 0: return 0; 9216 case 1: return 0; 9217 case 2: return -1; 9218 } 9219 case 1: return 0; 9220 case 2: 9221 switch(k) { 9222 case 0: return 1; 9223 case 1: return 0; 9224 case 2: return 0; 9225 } 9226 } 9227 case 2: 9228 switch(j) { 9229 case 0: 9230 switch(k) { 9231 case 0: return 0; 9232 case 1: return 1; 9233 case 2: return 0; 9234 } 9235 case 1: 9236 switch(k) { 9237 case 0: return -1; 9238 case 1: return 0; 9239 case 2: return 0; 9240 } 9241 case 2: return 0; 9242 } 9243 } 9244 return 0; 9245 } 9246 9247 #undef __FUNCT__ 9248 #define __FUNCT__ "DMPlexCreateRigidBody" 9249 /*@C 9250 DMPlexCreateRigidBody - create rigid body modes from coordinates 9251 9252 Collective on DM 9253 9254 Input Arguments: 9255 + dm - the DM 9256 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9257 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9258 9259 Output Argument: 9260 . sp - the null space 9261 9262 Note: This is necessary to take account of Dirichlet conditions on the displacements 9263 9264 Level: advanced 9265 9266 .seealso: MatNullSpaceCreate() 9267 @*/ 9268 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9269 { 9270 MPI_Comm comm = ((PetscObject) dm)->comm; 9271 Vec coordinates, localMode, mode[6]; 9272 PetscSection coordSection; 9273 PetscScalar *coords; 9274 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9275 PetscErrorCode ierr; 9276 9277 PetscFunctionBegin; 9278 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9279 if (dim == 1) { 9280 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9281 PetscFunctionReturn(0); 9282 } 9283 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9284 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9285 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9286 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9287 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9288 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9289 m = (dim*(dim+1))/2; 9290 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9291 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9292 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9293 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9294 /* Assume P1 */ 9295 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9296 for (d = 0; d < dim; ++d) { 9297 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9298 9299 values[d] = 1.0; 9300 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9301 for (v = vStart; v < vEnd; ++v) { 9302 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9303 } 9304 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9305 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9306 } 9307 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9308 for (d = dim; d < dim*(dim+1)/2; ++d) { 9309 PetscInt i, j, k = dim > 2 ? d - dim : d; 9310 9311 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9312 for (v = vStart; v < vEnd; ++v) { 9313 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9314 PetscInt off; 9315 9316 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9317 for (i = 0; i < dim; ++i) { 9318 for (j = 0; j < dim; ++j) { 9319 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9320 } 9321 } 9322 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9323 } 9324 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9325 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9326 } 9327 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9328 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9329 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9330 /* Orthonormalize system */ 9331 for (i = dim; i < m; ++i) { 9332 PetscScalar dots[6]; 9333 9334 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9335 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9336 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9337 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9338 } 9339 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9340 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9341 PetscFunctionReturn(0); 9342 } 9343 9344 #undef __FUNCT__ 9345 #define __FUNCT__ "DMPlexGetHybridBounds" 9346 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9347 { 9348 DM_Plex *mesh = (DM_Plex *) dm->data; 9349 PetscInt dim; 9350 PetscErrorCode ierr; 9351 9352 PetscFunctionBegin; 9353 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9354 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9355 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9356 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9357 if (eMax) *eMax = mesh->hybridPointMax[1]; 9358 if (vMax) *vMax = mesh->hybridPointMax[0]; 9359 PetscFunctionReturn(0); 9360 } 9361 9362 #undef __FUNCT__ 9363 #define __FUNCT__ "DMPlexSetHybridBounds" 9364 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9365 { 9366 DM_Plex *mesh = (DM_Plex *) dm->data; 9367 PetscInt dim; 9368 PetscErrorCode ierr; 9369 9370 PetscFunctionBegin; 9371 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9372 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9373 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9374 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9375 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9376 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9377 PetscFunctionReturn(0); 9378 } 9379 9380 #undef __FUNCT__ 9381 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9382 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9383 { 9384 DM_Plex *mesh = (DM_Plex *) dm->data; 9385 9386 PetscFunctionBegin; 9387 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9388 PetscValidPointer(cellHeight, 2); 9389 *cellHeight = mesh->vtkCellHeight; 9390 PetscFunctionReturn(0); 9391 } 9392 9393 #undef __FUNCT__ 9394 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9395 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9396 { 9397 DM_Plex *mesh = (DM_Plex *) dm->data; 9398 9399 PetscFunctionBegin; 9400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9401 mesh->vtkCellHeight = cellHeight; 9402 PetscFunctionReturn(0); 9403 } 9404 9405 #undef __FUNCT__ 9406 #define __FUNCT__ "DMPlexInsertFace_Private" 9407 /* 9408 DMPlexInsertFace_Private - Puts a face into the mesh 9409 9410 Not collective 9411 9412 Input Parameters: 9413 + dm - The DMPlex 9414 . numFaceVertex - The number of vertices in the face 9415 . faceVertices - The vertices in the face for dm 9416 . subfaceVertices - The vertices in the face for subdm 9417 . numCorners - The number of vertices in the cell 9418 . cell - A cell in dm containing the face 9419 . subcell - A cell in subdm containing the face 9420 . firstFace - First face in the mesh 9421 - newFacePoint - Next face in the mesh 9422 9423 Output Parameters: 9424 . newFacePoint - Contains next face point number on input, updated on output 9425 9426 Level: developer 9427 */ 9428 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) 9429 { 9430 MPI_Comm comm = ((PetscObject) dm)->comm; 9431 DM_Plex *submesh = (DM_Plex *) subdm->data; 9432 const PetscInt *faces; 9433 PetscInt numFaces, coneSize; 9434 PetscErrorCode ierr; 9435 9436 PetscFunctionBegin; 9437 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9438 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9439 #if 0 9440 /* Cannot use this because support() has not been constructed yet */ 9441 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9442 #else 9443 { 9444 PetscInt f; 9445 9446 numFaces = 0; 9447 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 9448 for(f = firstFace; f < *newFacePoint; ++f) { 9449 PetscInt dof, off, d; 9450 9451 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9452 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9453 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9454 for(d = 0; d < dof; ++d) { 9455 const PetscInt p = submesh->cones[off+d]; 9456 PetscInt v; 9457 9458 for(v = 0; v < numFaceVertices; ++v) { 9459 if (subfaceVertices[v] == p) break; 9460 } 9461 if (v == numFaceVertices) break; 9462 } 9463 if (d == dof) { 9464 numFaces = 1; 9465 ((PetscInt *) faces)[0] = f; 9466 } 9467 } 9468 } 9469 #endif 9470 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 9471 else if (numFaces == 1) { 9472 /* Add the other cell neighbor for this face */ 9473 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 9474 } else { 9475 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 9476 PetscBool posOriented; 9477 9478 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9479 origVertices = &orientedVertices[numFaceVertices]; 9480 indices = &orientedVertices[numFaceVertices*2]; 9481 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 9482 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 9483 /* TODO: I know that routine should return a permutation, not the indices */ 9484 for(v = 0; v < numFaceVertices; ++v) { 9485 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 9486 for(ov = 0; ov < numFaceVertices; ++ov) { 9487 if (orientedVertices[ov] == vertex) { 9488 orientedSubVertices[ov] = subvertex; 9489 break; 9490 } 9491 } 9492 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 9493 } 9494 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 9495 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 9496 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9497 ++(*newFacePoint); 9498 } 9499 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9500 PetscFunctionReturn(0); 9501 } 9502 9503 #undef __FUNCT__ 9504 #define __FUNCT__ "DMPlexCreateSubmesh" 9505 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 9506 { 9507 MPI_Comm comm = ((PetscObject) dm)->comm; 9508 DM_Plex *submesh; 9509 PetscBool boundaryFaces = PETSC_FALSE; 9510 PetscSection coordSection, subCoordSection; 9511 Vec coordinates, subCoordinates; 9512 PetscScalar *coords, *subCoords; 9513 IS labelIS; 9514 const PetscInt *subVertices; 9515 PetscInt *subVerticesActive, *tmpPoints; 9516 PetscInt *subCells = PETSC_NULL; 9517 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 9518 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 9519 PetscInt dim; /* Right now, do not specify dimension */ 9520 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 9521 PetscErrorCode ierr; 9522 9523 PetscFunctionBegin; 9524 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9525 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9526 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9527 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 9528 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9529 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9530 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9531 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9532 subface = &face[maxConeSize]; 9533 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 9534 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 9535 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 9536 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 9537 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 9538 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 9539 maxSubCells = numSubVertices; 9540 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 9541 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 9542 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 9543 for(v = 0; v < numSubVertices; ++v) { 9544 const PetscInt vertex = subVertices[v]; 9545 PetscInt *star = PETSC_NULL; 9546 PetscInt starSize, numCells = 0; 9547 9548 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9549 for(p = 0; p < starSize*2; p += 2) { 9550 const PetscInt point = star[p]; 9551 if ((point >= cStart) && (point < cEnd)) { 9552 star[numCells++] = point; 9553 } 9554 } 9555 numOldSubCells = numSubCells; 9556 for(c = 0; c < numCells; ++c) { 9557 const PetscInt cell = star[c]; 9558 PetscInt *closure = PETSC_NULL; 9559 PetscInt closureSize, numCorners = 0, faceSize = 0; 9560 PetscInt cellLoc; 9561 9562 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 9563 if (cellLoc >= 0) continue; 9564 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9565 for(p = 0; p < closureSize*2; p += 2) { 9566 const PetscInt point = closure[p]; 9567 if ((point >= vStart) && (point < vEnd)) { 9568 closure[numCorners++] = point; 9569 } 9570 } 9571 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 9572 for(corner = 0; corner < numCorners; ++corner) { 9573 const PetscInt cellVertex = closure[corner]; 9574 PetscInt subVertex; 9575 9576 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 9577 if (subVertex >= 0) { /* contains submesh vertex */ 9578 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9579 if (i == faceSize) { 9580 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 9581 face[faceSize] = cellVertex; 9582 subface[faceSize] = subVertex; 9583 ++faceSize; 9584 } 9585 } 9586 } 9587 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9588 if (faceSize >= nFV) { 9589 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9590 if (numSubCells >= maxSubCells) { 9591 PetscInt *tmpCells; 9592 maxSubCells *= 2; 9593 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 9594 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 9595 ierr = PetscFree(subCells);CHKERRQ(ierr); 9596 subCells = tmpCells; 9597 } 9598 /* TOOD: Maybe overestimate then squeeze out empty faces */ 9599 if (faceSize > nFV) { 9600 /* TODO: This is tricky. Maybe just add all faces */ 9601 numSubFaces++; 9602 } else { 9603 numSubFaces++; 9604 } 9605 for(f = 0; f < faceSize; ++f) { 9606 subVerticesActive[subface[f]] = 1; 9607 } 9608 subCells[numSubCells++] = cell; 9609 } 9610 } 9611 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9612 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 9613 } 9614 /* Pick out active subvertices */ 9615 for(v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 9616 if (subVerticesActive[v]) { 9617 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 9618 } 9619 } 9620 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 9621 /* Set cone sizes */ 9622 firstSubVertex = numSubCells; 9623 firstSubFace = numSubCells+numSubVerticesActive; 9624 newFacePoint = firstSubFace; 9625 for(c = 0; c < numSubCells; ++c) { 9626 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 9627 } 9628 for(f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 9629 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 9630 } 9631 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 9632 /* Create face cones */ 9633 for(c = 0; c < numSubCells; ++c) { 9634 const PetscInt cell = subCells[c]; 9635 PetscInt *closure = PETSC_NULL; 9636 PetscInt closureSize, numCorners = 0, faceSize = 0; 9637 9638 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9639 for(p = 0; p < closureSize*2; p += 2) { 9640 const PetscInt point = closure[p]; 9641 if ((point >= vStart) && (point < vEnd)) { 9642 closure[numCorners++] = point; 9643 } 9644 } 9645 for(corner = 0; corner < numCorners; ++corner) { 9646 const PetscInt cellVertex = closure[corner]; 9647 PetscInt subVertex; 9648 9649 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 9650 if (subVertex >= 0) { /* contains submesh vertex */ 9651 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9652 if (i == faceSize) { 9653 face[faceSize] = cellVertex; 9654 subface[faceSize] = numSubCells+subVertex; 9655 ++faceSize; 9656 } 9657 } 9658 } 9659 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9660 if (faceSize >= nFV) { 9661 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9662 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 9663 /* We have to take all the faces, and discard those in the interior */ 9664 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 9665 #if 0 9666 /* This object just calls insert on each face that comes from subsets() */ 9667 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 9668 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 9669 PointArray faceVec(face->begin(), face->end()); 9670 9671 subsets(faceVec, nFV, inserter); 9672 #endif 9673 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 9674 } 9675 } 9676 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 9677 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 9678 /* Build coordinates */ 9679 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9680 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9681 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 9682 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 9683 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 9684 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 9685 } 9686 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 9687 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 9688 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 9689 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 9690 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 9691 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9692 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9693 for(v = 0; v < numSubVerticesActive; ++v) { 9694 const PetscInt vertex = subVerticesActive[v]; 9695 const PetscInt subVertex = firstSubVertex+v; 9696 PetscInt dof, off, sdof, soff; 9697 9698 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 9699 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 9700 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 9701 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 9702 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 9703 for(d = 0; d < dof; ++d) { 9704 subCoords[soff+d] = coords[off+d]; 9705 } 9706 } 9707 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9708 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9709 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 9710 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 9711 9712 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 9713 /* Create map from submesh points to original mesh points */ 9714 submesh = (DM_Plex *) (*subdm)->data; 9715 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 9716 for(c = 0; c < numSubCells; ++c) { 9717 tmpPoints[c] = subCells[c]; 9718 } 9719 for(v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 9720 tmpPoints[v] = subVerticesActive[v-numSubCells]; 9721 } 9722 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 9723 9724 ierr = PetscFree(subCells);CHKERRQ(ierr); 9725 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 9726 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 9727 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 9728 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9729 PetscFunctionReturn(0); 9730 } 9731 9732 #undef __FUNCT__ 9733 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9734 /* We can easily have a form that takes an IS instead */ 9735 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9736 { 9737 PetscSection section, globalSection; 9738 PetscInt *numbers, p; 9739 PetscErrorCode ierr; 9740 9741 PetscFunctionBegin; 9742 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9743 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9744 for(p = pStart; p < pEnd; ++p) { 9745 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9746 } 9747 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9748 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9749 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9750 for(p = pStart; p < pEnd; ++p) { 9751 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9752 } 9753 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9754 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9755 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9756 PetscFunctionReturn(0); 9757 } 9758 9759 #undef __FUNCT__ 9760 #define __FUNCT__ "DMPlexGetCellNumbering" 9761 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9762 { 9763 DM_Plex *mesh = (DM_Plex *) dm->data; 9764 PetscInt cellHeight, cStart, cEnd, cMax; 9765 PetscErrorCode ierr; 9766 9767 PetscFunctionBegin; 9768 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9769 if (!mesh->globalCellNumbers) { 9770 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9771 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9772 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 9773 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9774 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9775 } 9776 *globalCellNumbers = mesh->globalCellNumbers; 9777 PetscFunctionReturn(0); 9778 } 9779 9780 #undef __FUNCT__ 9781 #define __FUNCT__ "DMPlexGetVertexNumbering" 9782 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9783 { 9784 DM_Plex *mesh = (DM_Plex *) dm->data; 9785 PetscInt vStart, vEnd, vMax; 9786 PetscErrorCode ierr; 9787 9788 PetscFunctionBegin; 9789 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9790 if (!mesh->globalVertexNumbers) { 9791 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9792 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9793 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9794 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9795 } 9796 *globalVertexNumbers = mesh->globalVertexNumbers; 9797 PetscFunctionReturn(0); 9798 } 9799 9800 #undef __FUNCT__ 9801 #define __FUNCT__ "DMPlexGetSubpointMap" 9802 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 9803 { 9804 DM_Plex *mesh = (DM_Plex *) dm->data; 9805 9806 PetscFunctionBegin; 9807 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9808 PetscValidPointer(subpointMap, 2); 9809 *subpointMap = mesh->subpointMap; 9810 PetscFunctionReturn(0); 9811 } 9812 9813 #undef __FUNCT__ 9814 #define __FUNCT__ "DMPlexSetSubpointMap" 9815 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 9816 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 9817 { 9818 DM_Plex *mesh = (DM_Plex *) dm->data; 9819 9820 PetscFunctionBegin; 9821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9822 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 9823 mesh->subpointMap = subpointMap; 9824 PetscFunctionReturn(0); 9825 } 9826 9827 #undef __FUNCT__ 9828 #define __FUNCT__ "DMPlexGetScale" 9829 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9830 { 9831 DM_Plex *mesh = (DM_Plex *) dm->data; 9832 9833 PetscFunctionBegin; 9834 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9835 PetscValidPointer(scale, 3); 9836 *scale = mesh->scale[unit]; 9837 PetscFunctionReturn(0); 9838 } 9839 9840 #undef __FUNCT__ 9841 #define __FUNCT__ "DMPlexSetScale" 9842 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9843 { 9844 DM_Plex *mesh = (DM_Plex *) dm->data; 9845 9846 PetscFunctionBegin; 9847 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9848 mesh->scale[unit] = scale; 9849 PetscFunctionReturn(0); 9850 } 9851 9852 9853 /******************************************************************************* 9854 This should be in a separate Discretization object, but I am not sure how to lay 9855 it out yet, so I am stuffing things here while I experiment. 9856 *******************************************************************************/ 9857 #undef __FUNCT__ 9858 #define __FUNCT__ "DMPlexSetFEMIntegration" 9859 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9860 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9861 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9862 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9863 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9864 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9865 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9866 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9867 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9868 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9869 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9870 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9871 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9872 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9873 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9874 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9875 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9876 { 9877 DM_Plex *mesh = (DM_Plex *) dm->data; 9878 9879 PetscFunctionBegin; 9880 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9881 mesh->integrateResidualFEM = integrateResidualFEM; 9882 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9883 mesh->integrateJacobianFEM = integrateJacobianFEM; 9884 PetscFunctionReturn(0); 9885 } 9886 9887 #undef __FUNCT__ 9888 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9889 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9890 { 9891 Vec coordinates; 9892 PetscSection section, cSection; 9893 PetscInt dim, vStart, vEnd, v, c, d; 9894 PetscScalar *values, *cArray; 9895 PetscReal *coords; 9896 PetscErrorCode ierr; 9897 9898 PetscFunctionBegin; 9899 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9900 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9901 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9902 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9903 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9904 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9905 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9906 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9907 for (v = vStart; v < vEnd; ++v) { 9908 PetscInt dof, off; 9909 9910 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9911 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9912 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9913 for(d = 0; d < dof; ++d) { 9914 coords[d] = PetscRealPart(cArray[off+d]); 9915 } 9916 for(c = 0; c < numComp; ++c) { 9917 values[c] = (*funcs[c])(coords); 9918 } 9919 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9920 } 9921 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9922 /* Temporary, must be replaced by a projection on the finite element basis */ 9923 { 9924 PetscInt eStart = 0, eEnd = 0, e, depth; 9925 9926 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9927 --depth; 9928 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9929 for (e = eStart; e < eEnd; ++e) { 9930 const PetscInt *cone = PETSC_NULL; 9931 PetscInt coneSize, d; 9932 PetscScalar *coordsA, *coordsB; 9933 9934 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9935 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9936 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9937 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9938 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9939 for (d = 0; d < dim; ++d) { 9940 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9941 } 9942 for (c = 0; c < numComp; ++c) { 9943 values[c] = (*funcs[c])(coords); 9944 } 9945 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9946 } 9947 } 9948 9949 ierr = PetscFree(coords);CHKERRQ(ierr); 9950 ierr = PetscFree(values);CHKERRQ(ierr); 9951 #if 0 9952 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9953 PetscReal detJ; 9954 9955 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9956 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9957 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV((int) pow(this->_mesh->getSieve()->getMaxConeSize(), dim+1)+1, true); 9958 9959 for (PetscInt c = cStart; c < cEnd; ++c) { 9960 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9961 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9962 const int oSize = pV.getSize(); 9963 int v = 0; 9964 9965 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 9966 for (PetscInt cl = 0; cl < oSize; ++cl) { 9967 const PetscInt fDim; 9968 9969 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9970 if (pointDim) { 9971 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9972 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9973 } 9974 } 9975 } 9976 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 9977 pV.clear(); 9978 } 9979 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9980 ierr = PetscFree(values);CHKERRQ(ierr); 9981 #endif 9982 PetscFunctionReturn(0); 9983 } 9984 9985 #undef __FUNCT__ 9986 #define __FUNCT__ "DMPlexProjectFunction" 9987 /*@C 9988 DMPlexProjectFunction - This projects the given function into the function space provided. 9989 9990 Input Parameters: 9991 + dm - The DM 9992 . numComp - The number of components (functions) 9993 . funcs - The coordinate functions to evaluate 9994 - mode - The insertion mode for values 9995 9996 Output Parameter: 9997 . X - vector 9998 9999 Level: developer 10000 10001 Note: 10002 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10003 We will eventually fix it. 10004 10005 ,seealso: DMPlexComputeL2Diff() 10006 */ 10007 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10008 { 10009 Vec localX; 10010 PetscErrorCode ierr; 10011 10012 PetscFunctionBegin; 10013 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10014 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10015 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10016 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10017 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10018 PetscFunctionReturn(0); 10019 } 10020 10021 #undef __FUNCT__ 10022 #define __FUNCT__ "DMPlexComputeL2Diff" 10023 /*@C 10024 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10025 10026 Input Parameters: 10027 + dm - The DM 10028 . quad - The PetscQuadrature object for each field 10029 . funcs - The functions to evaluate for each field component 10030 - X - The coefficient vector u_h 10031 10032 Output Parameter: 10033 . diff - The diff ||u - u_h||_2 10034 10035 Level: developer 10036 10037 .seealso: DMPlexProjectFunction() 10038 */ 10039 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) { 10040 const PetscInt debug = 0; 10041 PetscSection section; 10042 Vec localX; 10043 PetscReal *coords, *v0, *J, *invJ, detJ; 10044 PetscReal localDiff = 0.0; 10045 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10046 PetscErrorCode ierr; 10047 10048 PetscFunctionBegin; 10049 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10050 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10051 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10052 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10053 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10054 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10055 for (field = 0; field < numFields; ++field) { 10056 numComponents += quad[field].numComponents; 10057 } 10058 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10059 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10060 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10061 for (c = cStart; c < cEnd; ++c) { 10062 const PetscScalar *x; 10063 PetscReal elemDiff = 0.0; 10064 10065 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10066 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10067 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10068 10069 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10070 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10071 const PetscReal *quadPoints = quad[field].quadPoints; 10072 const PetscReal *quadWeights = quad[field].quadWeights; 10073 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10074 const PetscInt numBasisComps = quad[field].numComponents; 10075 const PetscReal *basis = quad[field].basis; 10076 PetscInt q, d, e, fc, f; 10077 10078 if (debug) { 10079 char title[1024]; 10080 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10081 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10082 } 10083 for (q = 0; q < numQuadPoints; ++q) { 10084 for (d = 0; d < dim; d++) { 10085 coords[d] = v0[d]; 10086 for (e = 0; e < dim; e++) { 10087 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10088 } 10089 } 10090 for (fc = 0; fc < numBasisComps; ++fc) { 10091 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10092 PetscReal interpolant = 0.0; 10093 for (f = 0; f < numBasisFuncs; ++f) { 10094 const PetscInt fidx = f*numBasisComps+fc; 10095 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10096 } 10097 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10098 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10099 } 10100 } 10101 comp += numBasisComps; 10102 fieldOffset += numBasisFuncs*numBasisComps; 10103 } 10104 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10105 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10106 localDiff += elemDiff; 10107 } 10108 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10109 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10110 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10111 *diff = PetscSqrtReal(*diff); 10112 PetscFunctionReturn(0); 10113 } 10114 10115 #undef __FUNCT__ 10116 #define __FUNCT__ "DMPlexComputeResidualFEM" 10117 /*@ 10118 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10119 10120 Input Parameters: 10121 + dm - The mesh 10122 . X - Local input vector 10123 - user - The user context 10124 10125 Output Parameter: 10126 . F - Local output vector 10127 10128 Note: 10129 The second member of the user context must be an FEMContext. 10130 10131 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10132 like a GPU, or vectorize on a multicore machine. 10133 10134 .seealso: DMPlexComputeJacobianActionFEM() 10135 */ 10136 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10137 { 10138 DM_Plex *mesh = (DM_Plex *) dm->data; 10139 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10140 PetscQuadrature *quad = fem->quad; 10141 PetscSection section; 10142 PetscReal *v0, *J, *invJ, *detJ; 10143 PetscScalar *elemVec, *u; 10144 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10145 PetscInt cellDof = 0, numComponents = 0; 10146 PetscErrorCode ierr; 10147 10148 PetscFunctionBegin; 10149 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10150 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10151 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10152 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10153 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10154 numCells = cEnd - cStart; 10155 for (field = 0; field < numFields; ++field) { 10156 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10157 numComponents += quad[field].numComponents; 10158 } 10159 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10160 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10161 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); 10162 for (c = cStart; c < cEnd; ++c) { 10163 const PetscScalar *x; 10164 PetscInt i; 10165 10166 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10167 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10168 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10169 10170 for (i = 0; i < cellDof; ++i) { 10171 u[c*cellDof+i] = x[i]; 10172 } 10173 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10174 } 10175 for (field = 0; field < numFields; ++field) { 10176 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10177 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10178 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10179 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10180 /* Conforming batches */ 10181 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10182 PetscInt numBlocks = 1; 10183 PetscInt batchSize = numBlocks * blockSize; 10184 PetscInt numBatches = numBatchesTmp; 10185 PetscInt numChunks = numCells / (numBatches*batchSize); 10186 /* Remainder */ 10187 PetscInt numRemainder = numCells % (numBatches * batchSize); 10188 PetscInt offset = numCells - numRemainder; 10189 10190 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10191 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10192 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10193 } 10194 for (c = cStart; c < cEnd; ++c) { 10195 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10196 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10197 } 10198 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10199 if (mesh->printFEM) { 10200 PetscMPIInt rank, numProcs; 10201 PetscInt p; 10202 10203 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10204 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10205 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10206 for (p = 0; p < numProcs; ++p) { 10207 if (p == rank) { 10208 Vec f; 10209 10210 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10211 ierr = VecCopy(F, f);CHKERRQ(ierr); 10212 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10213 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10214 ierr = VecDestroy(&f);CHKERRQ(ierr); 10215 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10216 } 10217 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10218 } 10219 } 10220 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10221 PetscFunctionReturn(0); 10222 } 10223 10224 #undef __FUNCT__ 10225 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10226 /*@C 10227 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10228 10229 Input Parameters: 10230 + dm - The mesh 10231 . J - The Jacobian shell matrix 10232 . X - Local input vector 10233 - user - The user context 10234 10235 Output Parameter: 10236 . F - Local output vector 10237 10238 Note: 10239 The second member of the user context must be an FEMContext. 10240 10241 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10242 like a GPU, or vectorize on a multicore machine. 10243 10244 .seealso: DMPlexComputeResidualFEM() 10245 */ 10246 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10247 { 10248 DM_Plex *mesh = (DM_Plex *) dm->data; 10249 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10250 PetscQuadrature *quad = fem->quad; 10251 PetscSection section; 10252 JacActionCtx *jctx; 10253 PetscReal *v0, *J, *invJ, *detJ; 10254 PetscScalar *elemVec, *u, *a; 10255 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10256 PetscInt cellDof = 0; 10257 PetscErrorCode ierr; 10258 10259 PetscFunctionBegin; 10260 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10261 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10262 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10263 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10264 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10265 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10266 numCells = cEnd - cStart; 10267 for (field = 0; field < numFields; ++field) { 10268 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10269 } 10270 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10271 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); 10272 for (c = cStart; c < cEnd; ++c) { 10273 const PetscScalar *x; 10274 PetscInt i; 10275 10276 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10277 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10278 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10279 for (i = 0; i < cellDof; ++i) { 10280 u[c*cellDof+i] = x[i]; 10281 } 10282 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10283 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10284 for (i = 0; i < cellDof; ++i) { 10285 a[c*cellDof+i] = x[i]; 10286 } 10287 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10288 } 10289 for (field = 0; field < numFields; ++field) { 10290 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10291 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10292 /* Conforming batches */ 10293 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10294 PetscInt numBlocks = 1; 10295 PetscInt batchSize = numBlocks * blockSize; 10296 PetscInt numBatches = numBatchesTmp; 10297 PetscInt numChunks = numCells / (numBatches*batchSize); 10298 /* Remainder */ 10299 PetscInt numRemainder = numCells % (numBatches * batchSize); 10300 PetscInt offset = numCells - numRemainder; 10301 10302 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); 10303 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], 10304 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10305 } 10306 for (c = cStart; c < cEnd; ++c) { 10307 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10308 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10309 } 10310 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10311 if (mesh->printFEM) { 10312 PetscMPIInt rank, numProcs; 10313 PetscInt p; 10314 10315 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10316 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10317 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10318 for (p = 0; p < numProcs; ++p) { 10319 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10320 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10321 } 10322 } 10323 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10324 PetscFunctionReturn(0); 10325 } 10326 10327 #undef __FUNCT__ 10328 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10329 /*@ 10330 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10331 10332 Input Parameters: 10333 + dm - The mesh 10334 . X - Local input vector 10335 - user - The user context 10336 10337 Output Parameter: 10338 . Jac - Jacobian matrix 10339 10340 Note: 10341 The second member of the user context must be an FEMContext. 10342 10343 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10344 like a GPU, or vectorize on a multicore machine. 10345 10346 .seealso: FormFunctionLocal() 10347 */ 10348 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10349 { 10350 DM_Plex *mesh = (DM_Plex *) dm->data; 10351 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10352 PetscQuadrature *quad = fem->quad; 10353 PetscSection section; 10354 PetscReal *v0, *J, *invJ, *detJ; 10355 PetscScalar *elemMat, *u; 10356 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10357 PetscInt cellDof = 0, numComponents = 0; 10358 PetscBool isShell; 10359 PetscErrorCode ierr; 10360 10361 PetscFunctionBegin; 10362 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10363 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10364 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10365 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10366 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10367 numCells = cEnd - cStart; 10368 for (field = 0; field < numFields; ++field) { 10369 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10370 numComponents += quad[field].numComponents; 10371 } 10372 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10373 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10374 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); 10375 for (c = cStart; c < cEnd; ++c) { 10376 const PetscScalar *x; 10377 PetscInt i; 10378 10379 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10380 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10381 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10382 10383 for (i = 0; i < cellDof; ++i) { 10384 u[c*cellDof+i] = x[i]; 10385 } 10386 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10387 } 10388 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10389 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10390 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10391 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10392 PetscInt fieldJ; 10393 10394 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10395 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10396 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10397 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10398 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10399 /* Conforming batches */ 10400 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10401 PetscInt numBlocks = 1; 10402 PetscInt batchSize = numBlocks * blockSize; 10403 PetscInt numBatches = numBatchesTmp; 10404 PetscInt numChunks = numCells / (numBatches*batchSize); 10405 /* Remainder */ 10406 PetscInt numRemainder = numCells % (numBatches * batchSize); 10407 PetscInt offset = numCells - numRemainder; 10408 10409 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10410 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10411 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10412 } 10413 } 10414 for (c = cStart; c < cEnd; ++c) { 10415 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10416 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10417 } 10418 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10419 10420 /* Assemble matrix, using the 2-step process: 10421 MatAssemblyBegin(), MatAssemblyEnd(). */ 10422 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10423 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10424 10425 if (mesh->printFEM) { 10426 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10427 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10428 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10429 } 10430 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10431 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10432 if (isShell) { 10433 JacActionCtx *jctx; 10434 10435 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10436 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10437 } 10438 *str = SAME_NONZERO_PATTERN; 10439 PetscFunctionReturn(0); 10440 } 10441 10442 10443 #undef __FUNCT__ 10444 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10445 /*@C 10446 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10447 the local section and an SF describing the section point overlap. 10448 10449 Input Parameters: 10450 + s - The PetscSection for the local field layout 10451 . sf - The SF describing parallel layout of the section points 10452 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10453 . label - The label specifying the points 10454 - labelValue - The label stratum specifying the points 10455 10456 Output Parameter: 10457 . gsection - The PetscSection for the global field layout 10458 10459 Note: This gives negative sizes and offsets to points not owned by this process 10460 10461 Level: developer 10462 10463 .seealso: PetscSectionCreate() 10464 @*/ 10465 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10466 { 10467 PetscInt *neg; 10468 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10469 PetscErrorCode ierr; 10470 10471 PetscFunctionBegin; 10472 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10473 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10474 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10475 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10476 /* Mark ghost points with negative dof */ 10477 for (p = pStart; p < pEnd; ++p) { 10478 PetscInt value; 10479 10480 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 10481 if (value != labelValue) continue; 10482 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 10483 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 10484 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 10485 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 10486 neg[p-pStart] = -(dof+1); 10487 } 10488 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 10489 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10490 if (nroots >= 0) { 10491 if (nroots > pEnd - pStart) { 10492 PetscInt *tmpDof; 10493 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10494 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 10495 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10496 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10497 for (p = pStart; p < pEnd; ++p) { 10498 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 10499 } 10500 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 10501 } else { 10502 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10503 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10504 } 10505 } 10506 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 10507 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10508 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 10509 (*gsection)->atlasOff[p] = off; 10510 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 10511 } 10512 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 10513 globalOff -= off; 10514 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10515 (*gsection)->atlasOff[p] += globalOff; 10516 neg[p] = -((*gsection)->atlasOff[p]+1); 10517 } 10518 /* Put in negative offsets for ghost points */ 10519 if (nroots >= 0) { 10520 if (nroots > pEnd - pStart) { 10521 PetscInt *tmpOff; 10522 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10523 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 10524 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10525 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10526 for (p = pStart; p < pEnd; ++p) { 10527 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 10528 } 10529 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 10530 } else { 10531 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10532 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10533 } 10534 } 10535 ierr = PetscFree(neg);CHKERRQ(ierr); 10536 PetscFunctionReturn(0); 10537 } 10538