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, "\\documentclass{article}\n\n\ 191 \\usepackage{tikz}\n\ 192 \\usepackage{pgflibraryshapes}\n\ 193 \\usetikzlibrary{backgrounds}\n\ 194 \\usetikzlibrary{arrows}\n\ 195 \\newenvironment{changemargin}[2]{%%\n\ 196 \\begin{list}{}{%%\n\ 197 \\setlength{\\topsep}{0pt}%%\n\ 198 \\setlength{\\leftmargin}{#1}%%\n\ 199 \\setlength{\\rightmargin}{#2}%%\n\ 200 \\setlength{\\listparindent}{\\parindent}%%\n\ 201 \\setlength{\\itemindent}{\\parindent}%%\n\ 202 \\setlength{\\parsep}{\\parskip}%%\n\ 203 }%%\n\ 204 \\item[]}{\\end{list}}\n\n\ 205 \\begin{document}\n\ 206 \\section{%s}\n\ 207 \\begin{changemargin}{-1cm}{0cm}\n\ 208 \\begin{center}\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", name, 8.0/scale);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, "Mesh for process ");CHKERRQ(ierr); 276 for(p = 0; p < size; ++p) { 277 if (p > 0 && p == size-1) { 278 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 279 } else if (p > 0) { 280 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 281 } 282 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 283 } 284 ierr = PetscViewerASCIIPrintf(viewer, ".\n");CHKERRQ(ierr); 285 ierr = PetscViewerASCIIPrintf(viewer, "\\end{changemargin}\n\ 286 \\end{document}\n", name);CHKERRQ(ierr); 287 } else { 288 MPI_Comm comm = ((PetscObject) dm)->comm; 289 PetscInt *sizes; 290 PetscInt locDepth, depth, dim, d; 291 PetscInt pStart, pEnd, p; 292 PetscMPIInt size; 293 294 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 295 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 296 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 297 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 298 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 299 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 300 if (depth == 1) { 301 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 302 pEnd = pEnd - pStart; 303 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 304 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 305 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 306 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 307 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 308 pEnd = pEnd - pStart; 309 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 310 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 311 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 312 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 313 } else { 314 for (d = 0; d <= dim; d++) { 315 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 316 pEnd = pEnd - pStart; 317 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 318 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 319 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 320 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 321 } 322 } 323 ierr = PetscFree(sizes);CHKERRQ(ierr); 324 } 325 PetscFunctionReturn(0); 326 } 327 328 #undef __FUNCT__ 329 #define __FUNCT__ "DMView_Plex" 330 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 331 { 332 PetscBool iascii, isbinary; 333 PetscErrorCode ierr; 334 335 PetscFunctionBegin; 336 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 337 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 338 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 339 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 340 if (iascii) { 341 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 342 #if 0 343 } else if (isbinary) { 344 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 345 #endif 346 } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name); 347 PetscFunctionReturn(0); 348 } 349 350 #undef __FUNCT__ 351 #define __FUNCT__ "DMDestroy_Plex" 352 PetscErrorCode DMDestroy_Plex(DM dm) 353 { 354 DM_Plex *mesh = (DM_Plex *) dm->data; 355 DMLabel next = mesh->labels; 356 PetscErrorCode ierr; 357 358 PetscFunctionBegin; 359 if (--mesh->refct > 0) {PetscFunctionReturn(0);} 360 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 361 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 362 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 363 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 364 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 365 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 366 while(next) { 367 DMLabel tmp = next->next; 368 369 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 370 next = tmp; 371 } 372 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 373 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 374 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 375 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 376 ierr = PetscFree(mesh);CHKERRQ(ierr); 377 PetscFunctionReturn(0); 378 } 379 380 #undef __FUNCT__ 381 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 382 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 383 { 384 const PetscInt *support = PETSC_NULL; 385 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 386 PetscErrorCode ierr; 387 388 PetscFunctionBegin; 389 if (useClosure) { 390 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 391 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 392 for (s = 0; s < supportSize; ++s) { 393 const PetscInt *cone = PETSC_NULL; 394 PetscInt coneSize, c, q; 395 396 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 397 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 398 for (c = 0; c < coneSize; ++c) { 399 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 400 if (cone[c] == adj[q]) break; 401 } 402 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 403 } 404 } 405 } else { 406 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 407 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 408 for (s = 0; s < supportSize; ++s) { 409 const PetscInt *cone = PETSC_NULL; 410 PetscInt coneSize, c, q; 411 412 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 413 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 414 for (c = 0; c < coneSize; ++c) { 415 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 416 if (cone[c] == adj[q]) break; 417 } 418 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 419 } 420 } 421 } 422 *adjSize = numAdj; 423 PetscFunctionReturn(0); 424 } 425 426 #undef __FUNCT__ 427 #define __FUNCT__ "DMPlexGetAdjacency_Private" 428 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 429 { 430 const PetscInt *star = tmpClosure; 431 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 432 PetscErrorCode ierr; 433 434 PetscFunctionBegin; 435 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr); 436 for (s = 2; s < starSize*2; s += 2) { 437 const PetscInt *closure = PETSC_NULL; 438 PetscInt closureSize, c, q; 439 440 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 441 for (c = 0; c < closureSize*2; c += 2) { 442 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 443 if (closure[c] == adj[q]) break; 444 } 445 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 446 } 447 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 448 } 449 *adjSize = numAdj; 450 PetscFunctionReturn(0); 451 } 452 453 #undef __FUNCT__ 454 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 455 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 456 { 457 DM_Plex *mesh = (DM_Plex *) dm->data; 458 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 461 mesh->preallocCenterDim = preallocCenterDim; 462 PetscFunctionReturn(0); 463 } 464 465 #undef __FUNCT__ 466 #define __FUNCT__ "DMPlexPreallocateOperator" 467 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 468 { 469 DM_Plex *mesh = (DM_Plex *) dm->data; 470 MPI_Comm comm = ((PetscObject) dm)->comm; 471 PetscSF sf, sfDof, sfAdj; 472 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 473 PetscInt nleaves, l, p; 474 const PetscInt *leaves; 475 const PetscSFNode *remotes; 476 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 477 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 478 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 479 PetscLayout rLayout; 480 PetscInt locRows, rStart, rEnd, r; 481 PetscMPIInt size; 482 PetscBool useClosure, debug = PETSC_FALSE; 483 PetscErrorCode ierr; 484 485 PetscFunctionBegin; 486 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 487 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 488 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 489 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 490 /* Create dof SF based on point SF */ 491 if (debug) { 492 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 493 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 494 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 495 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 496 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 497 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 498 } 499 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 500 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 501 if (debug) { 502 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 503 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 504 } 505 /* Create section for dof adjacency (dof ==> # adj dof) */ 506 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 507 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 508 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 509 if (mesh->preallocCenterDim == dim) { 510 useClosure = PETSC_FALSE; 511 } else if (mesh->preallocCenterDim == 0) { 512 useClosure = PETSC_TRUE; 513 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 514 515 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 516 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 517 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 518 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 519 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 520 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 521 /* Fill in the ghost dofs on the interface */ 522 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 523 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 524 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 525 maxClosureSize = (PetscInt) (2*PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1)); 526 maxAdjSize = (PetscInt) (pow((PetscReal) mesh->maxConeSize, depth)*pow((PetscReal) mesh->maxSupportSize, depth)+1); 527 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 528 529 /* 530 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 531 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 532 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 533 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 534 Create sfAdj connecting rootSectionAdj and leafSectionAdj 535 3. Visit unowned points on interface, write adjacencies to adj 536 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 537 4. Visit owned points on interface, write adjacencies to rootAdj 538 Remove redundancy in rootAdj 539 ** The last two traversals use transitive closure 540 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 541 Allocate memory addressed by sectionAdj (cols) 542 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 543 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 544 */ 545 546 for (l = 0; l < nleaves; ++l) { 547 PetscInt dof, off, d, q; 548 PetscInt p = leaves[l], numAdj = maxAdjSize; 549 550 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 551 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 552 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 553 for (q = 0; q < numAdj; ++q) { 554 PetscInt ndof, ncdof; 555 556 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 557 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 558 for (d = off; d < off+dof; ++d) { 559 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 560 } 561 } 562 } 563 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 564 if (debug) { 565 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 566 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 567 } 568 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 569 if (size > 1) { 570 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 571 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 572 } 573 if (debug) { 574 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 575 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 576 } 577 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 578 for (p = pStart; p < pEnd; ++p) { 579 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 580 581 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 582 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 583 if (!dof) continue; 584 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 585 if (adof <= 0) continue; 586 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 587 for (q = 0; q < numAdj; ++q) { 588 PetscInt ndof, ncdof; 589 590 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 591 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 592 for (d = off; d < off+dof; ++d) { 593 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 594 } 595 } 596 } 597 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 598 if (debug) { 599 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 600 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 601 } 602 /* Create adj SF based on dof SF */ 603 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 604 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 605 if (debug) { 606 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 607 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 608 } 609 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 610 /* Create leaf adjacency */ 611 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 612 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 613 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 614 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 615 for (l = 0; l < nleaves; ++l) { 616 PetscInt dof, off, d, q; 617 PetscInt p = leaves[l], numAdj = maxAdjSize; 618 619 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 620 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 621 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 622 for (d = off; d < off+dof; ++d) { 623 PetscInt aoff, i = 0; 624 625 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 626 for (q = 0; q < numAdj; ++q) { 627 PetscInt ndof, ncdof, ngoff, nd; 628 629 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 630 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 631 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 632 for (nd = 0; nd < ndof-ncdof; ++nd) { 633 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 634 ++i; 635 } 636 } 637 } 638 } 639 /* Debugging */ 640 if (debug) { 641 IS tmp; 642 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 643 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 644 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 645 } 646 /* Gather adjacenct indices to root */ 647 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 648 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 649 for (r = 0; r < adjSize; ++r) { 650 rootAdj[r] = -1; 651 } 652 if (size > 1) { 653 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 654 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 655 } 656 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 657 ierr = PetscFree(adj);CHKERRQ(ierr); 658 /* Debugging */ 659 if (debug) { 660 IS tmp; 661 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 662 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 663 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 664 } 665 /* Add in local adjacency indices for owned dofs on interface (roots) */ 666 for (p = pStart; p < pEnd; ++p) { 667 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 668 669 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 670 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 671 if (!dof) continue; 672 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 673 if (adof <= 0) continue; 674 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 675 for (d = off; d < off+dof; ++d) { 676 PetscInt adof, aoff, i; 677 678 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 679 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 680 i = adof-1; 681 for (q = 0; q < numAdj; ++q) { 682 PetscInt ndof, ncdof, ngoff, nd; 683 684 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 685 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 686 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 687 for (nd = 0; nd < ndof-ncdof; ++nd) { 688 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 689 --i; 690 } 691 } 692 } 693 } 694 /* Debugging */ 695 if (debug) { 696 IS tmp; 697 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 698 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 699 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 700 } 701 /* Compress indices */ 702 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 703 for (p = pStart; p < pEnd; ++p) { 704 PetscInt dof, cdof, off, d; 705 PetscInt adof, aoff; 706 707 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 708 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 709 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 710 if (!dof) continue; 711 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 712 if (adof <= 0) continue; 713 for (d = off; d < off+dof-cdof; ++d) { 714 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 715 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 716 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 717 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 718 } 719 } 720 /* Debugging */ 721 if (debug) { 722 IS tmp; 723 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 724 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 725 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 726 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 727 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 728 } 729 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 730 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 731 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 732 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 733 for (p = pStart; p < pEnd; ++p) { 734 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 735 PetscBool found = PETSC_TRUE; 736 737 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 738 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 739 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 740 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 741 for (d = 0; d < dof-cdof; ++d) { 742 PetscInt ldof, rdof; 743 744 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 745 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 746 if (ldof > 0) { 747 /* We do not own this point */ 748 } else if (rdof > 0) { 749 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 750 } else { 751 found = PETSC_FALSE; 752 } 753 } 754 if (found) continue; 755 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 756 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 757 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 758 for (q = 0; q < numAdj; ++q) { 759 PetscInt ndof, ncdof, noff; 760 761 /* Adjacent points may not be in the section chart */ 762 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 763 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 764 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 765 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 766 for (d = goff; d < goff+dof-cdof; ++d) { 767 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 768 } 769 } 770 } 771 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 772 if (debug) { 773 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 774 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 775 } 776 /* Get adjacent indices */ 777 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 778 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 779 for (p = pStart; p < pEnd; ++p) { 780 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 781 PetscBool found = PETSC_TRUE; 782 783 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 784 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 786 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 787 for (d = 0; d < dof-cdof; ++d) { 788 PetscInt ldof, rdof; 789 790 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 791 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 792 if (ldof > 0) { 793 /* We do not own this point */ 794 } else if (rdof > 0) { 795 PetscInt aoff, roff; 796 797 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 798 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 799 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 800 } else { 801 found = PETSC_FALSE; 802 } 803 } 804 if (found) continue; 805 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 806 for (d = goff; d < goff+dof-cdof; ++d) { 807 PetscInt adof, aoff, i = 0; 808 809 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 810 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 811 for (q = 0; q < numAdj; ++q) { 812 PetscInt ndof, ncdof, ngoff, nd; 813 const PetscInt *ncind; 814 815 /* Adjacent points may not be in the section chart */ 816 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 817 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 818 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 819 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 820 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 821 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 822 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 823 } 824 } 825 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 826 } 827 } 828 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 829 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 830 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 831 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 832 /* Debugging */ 833 if (debug) { 834 IS tmp; 835 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 836 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 837 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 838 } 839 /* Create allocation vectors from adjacency graph */ 840 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 841 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 842 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 843 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 844 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 845 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 846 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 847 /* Only loop over blocks of rows */ 848 if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 849 for (r = rStart/bs; r < rEnd/bs; ++r) { 850 const PetscInt row = r*bs; 851 PetscInt numCols, cStart, c; 852 853 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 854 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 855 for (c = cStart; c < cStart+numCols; ++c) { 856 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 857 ++dnz[r-rStart]; 858 if (cols[c] >= row) {++dnzu[r-rStart];} 859 } else { 860 ++onz[r-rStart]; 861 if (cols[c] >= row) {++onzu[r-rStart];} 862 } 863 } 864 } 865 if (bs > 1) { 866 for (r = 0; r < locRows/bs; ++r) { 867 dnz[r] /= bs; 868 onz[r] /= bs; 869 dnzu[r] /= bs; 870 onzu[r] /= bs; 871 } 872 } 873 /* Set matrix pattern */ 874 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 875 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 876 /* Fill matrix with zeros */ 877 if (fillMatrix) { 878 PetscScalar *values; 879 PetscInt maxRowLen = 0; 880 881 for (r = rStart; r < rEnd; ++r) { 882 PetscInt len; 883 884 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 885 maxRowLen = PetscMax(maxRowLen, len); 886 } 887 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 888 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 889 for (r = rStart; r < rEnd; ++r) { 890 PetscInt numCols, cStart; 891 892 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 893 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 894 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 895 } 896 ierr = PetscFree(values);CHKERRQ(ierr); 897 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 898 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 899 } 900 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 901 ierr = PetscFree(cols);CHKERRQ(ierr); 902 PetscFunctionReturn(0); 903 } 904 905 #if 0 906 #undef __FUNCT__ 907 #define __FUNCT__ "DMPlexPreallocateOperator_2" 908 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 909 { 910 PetscErrorCode ierr; 911 PetscInt c,cStart,cEnd,pStart,pEnd; 912 PetscInt *tmpClosure,*tmpAdj,*visits; 913 914 PetscFunctionBegin; 915 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 916 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 917 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 918 maxClosureSize = 2*PetscMax(pow(mesh->maxConeSize, depth)+1, pow(mesh->maxSupportSize, depth)+1); 919 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 920 npoints = pEnd - pStart; 921 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 922 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 923 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 924 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 925 for (c=cStart; c<cEnd; c++) { 926 PetscInt *support = tmpClosure; 927 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 928 for (p=0; p<supportSize; p++) { 929 lvisits[support[p]]++; 930 } 931 } 932 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 933 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 934 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 935 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 936 937 ierr = PetscSFGetRanks();CHKERRQ(ierr); 938 939 940 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 941 for (c=cStart; c<cEnd; c++) { 942 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 943 /* 944 Depth-first walk of transitive closure. 945 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. 946 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 947 */ 948 } 949 950 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 951 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 952 PetscFunctionReturn(0); 953 } 954 #endif 955 956 #undef __FUNCT__ 957 #define __FUNCT__ "DMCreateMatrix_Plex" 958 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 959 { 960 PetscSection section, sectionGlobal; 961 PetscInt bs = -1; 962 PetscInt localSize; 963 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 964 PetscErrorCode ierr; 965 966 PetscFunctionBegin; 967 #ifndef PETSC_USE_DYNAMIC_LIBRARIES 968 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 969 #endif 970 if (!mtype) mtype = MATAIJ; 971 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 972 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 973 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 974 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 975 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 976 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 977 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 978 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 979 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 980 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 981 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 982 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 983 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 984 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 985 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 986 /* Check for symmetric storage */ 987 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 988 if (isSymmetric) { 989 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 990 } 991 if (!isShell) { 992 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 993 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal; 994 995 if (bs < 0) { 996 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 997 PetscInt pStart, pEnd, p, dof; 998 999 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1000 for (p = pStart; p < pEnd; ++p) { 1001 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1002 if (dof) { 1003 bs = dof; 1004 break; 1005 } 1006 } 1007 } else { 1008 bs = 1; 1009 } 1010 /* Must have same blocksize on all procs (some might have no points) */ 1011 bsLocal = bs; 1012 ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1013 } 1014 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1015 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1016 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1017 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1018 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1019 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1020 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1021 } 1022 PetscFunctionReturn(0); 1023 } 1024 1025 #undef __FUNCT__ 1026 #define __FUNCT__ "DMPlexGetDimension" 1027 /*@ 1028 DMPlexGetDimension - Return the topological mesh dimension 1029 1030 Not collective 1031 1032 Input Parameter: 1033 . mesh - The DMPlex 1034 1035 Output Parameter: 1036 . dim - The topological mesh dimension 1037 1038 Level: beginner 1039 1040 .seealso: DMPlexCreate() 1041 @*/ 1042 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1043 { 1044 DM_Plex *mesh = (DM_Plex *) dm->data; 1045 1046 PetscFunctionBegin; 1047 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1048 PetscValidPointer(dim, 2); 1049 *dim = mesh->dim; 1050 PetscFunctionReturn(0); 1051 } 1052 1053 #undef __FUNCT__ 1054 #define __FUNCT__ "DMPlexSetDimension" 1055 /*@ 1056 DMPlexSetDimension - Set the topological mesh dimension 1057 1058 Collective on mesh 1059 1060 Input Parameters: 1061 + mesh - The DMPlex 1062 - dim - The topological mesh dimension 1063 1064 Level: beginner 1065 1066 .seealso: DMPlexCreate() 1067 @*/ 1068 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1069 { 1070 DM_Plex *mesh = (DM_Plex *) dm->data; 1071 1072 PetscFunctionBegin; 1073 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1074 PetscValidLogicalCollectiveInt(dm, dim, 2); 1075 mesh->dim = dim; 1076 mesh->preallocCenterDim = dim; 1077 PetscFunctionReturn(0); 1078 } 1079 1080 #undef __FUNCT__ 1081 #define __FUNCT__ "DMPlexGetChart" 1082 /*@ 1083 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1084 1085 Not collective 1086 1087 Input Parameter: 1088 . mesh - The DMPlex 1089 1090 Output Parameters: 1091 + pStart - The first mesh point 1092 - pEnd - The upper bound for mesh points 1093 1094 Level: beginner 1095 1096 .seealso: DMPlexCreate(), DMPlexSetChart() 1097 @*/ 1098 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1099 { 1100 DM_Plex *mesh = (DM_Plex *) dm->data; 1101 PetscErrorCode ierr; 1102 1103 PetscFunctionBegin; 1104 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1105 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1106 PetscFunctionReturn(0); 1107 } 1108 1109 #undef __FUNCT__ 1110 #define __FUNCT__ "DMPlexSetChart" 1111 /*@ 1112 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1113 1114 Not collective 1115 1116 Input Parameters: 1117 + mesh - The DMPlex 1118 . pStart - The first mesh point 1119 - pEnd - The upper bound for mesh points 1120 1121 Output Parameters: 1122 1123 Level: beginner 1124 1125 .seealso: DMPlexCreate(), DMPlexGetChart() 1126 @*/ 1127 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1128 { 1129 DM_Plex *mesh = (DM_Plex *) dm->data; 1130 PetscErrorCode ierr; 1131 1132 PetscFunctionBegin; 1133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1134 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1135 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1136 PetscFunctionReturn(0); 1137 } 1138 1139 #undef __FUNCT__ 1140 #define __FUNCT__ "DMPlexGetConeSize" 1141 /*@ 1142 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1143 1144 Not collective 1145 1146 Input Parameters: 1147 + mesh - The DMPlex 1148 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1149 1150 Output Parameter: 1151 . size - The cone size for point p 1152 1153 Level: beginner 1154 1155 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1156 @*/ 1157 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1158 { 1159 DM_Plex *mesh = (DM_Plex *) dm->data; 1160 PetscErrorCode ierr; 1161 1162 PetscFunctionBegin; 1163 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1164 PetscValidPointer(size, 3); 1165 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1166 PetscFunctionReturn(0); 1167 } 1168 1169 #undef __FUNCT__ 1170 #define __FUNCT__ "DMPlexSetConeSize" 1171 /*@ 1172 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1173 1174 Not collective 1175 1176 Input Parameters: 1177 + mesh - The DMPlex 1178 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1179 - size - The cone size for point p 1180 1181 Output Parameter: 1182 1183 Note: 1184 This should be called after DMPlexSetChart(). 1185 1186 Level: beginner 1187 1188 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1189 @*/ 1190 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1191 { 1192 DM_Plex *mesh = (DM_Plex *) dm->data; 1193 PetscErrorCode ierr; 1194 1195 PetscFunctionBegin; 1196 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1197 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1198 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1199 PetscFunctionReturn(0); 1200 } 1201 1202 #undef __FUNCT__ 1203 #define __FUNCT__ "DMPlexGetCone" 1204 /*@C 1205 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1206 1207 Not collective 1208 1209 Input Parameters: 1210 + mesh - The DMPlex 1211 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1212 1213 Output Parameter: 1214 . cone - An array of points which are on the in-edges for point p 1215 1216 Level: beginner 1217 1218 Note: 1219 This routine is not available in Fortran. 1220 1221 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1222 @*/ 1223 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1224 { 1225 DM_Plex *mesh = (DM_Plex *) dm->data; 1226 PetscInt off; 1227 PetscErrorCode ierr; 1228 1229 PetscFunctionBegin; 1230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1231 PetscValidPointer(cone, 3); 1232 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1233 *cone = &mesh->cones[off]; 1234 PetscFunctionReturn(0); 1235 } 1236 1237 #undef __FUNCT__ 1238 #define __FUNCT__ "DMPlexSetCone" 1239 /*@ 1240 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1241 1242 Not collective 1243 1244 Input Parameters: 1245 + mesh - The DMPlex 1246 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1247 - cone - An array of points which are on the in-edges for point p 1248 1249 Output Parameter: 1250 1251 Note: 1252 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1253 1254 Level: beginner 1255 1256 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1257 @*/ 1258 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1259 { 1260 DM_Plex *mesh = (DM_Plex *) dm->data; 1261 PetscInt pStart, pEnd; 1262 PetscInt dof, off, c; 1263 PetscErrorCode ierr; 1264 1265 PetscFunctionBegin; 1266 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1267 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1268 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1269 if (dof) PetscValidPointer(cone, 3); 1270 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1271 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); 1272 for (c = 0; c < dof; ++c) { 1273 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); 1274 mesh->cones[off+c] = cone[c]; 1275 } 1276 PetscFunctionReturn(0); 1277 } 1278 1279 #undef __FUNCT__ 1280 #define __FUNCT__ "DMPlexGetConeOrientation" 1281 /*@C 1282 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1283 1284 Not collective 1285 1286 Input Parameters: 1287 + mesh - The DMPlex 1288 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1289 1290 Output Parameter: 1291 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1292 integer giving the prescription for cone traversal. If it is negative, the cone is 1293 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1294 the index of the cone point on which to start. 1295 1296 Level: beginner 1297 1298 Note: 1299 This routine is not available in Fortran. 1300 1301 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1302 @*/ 1303 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1304 { 1305 DM_Plex *mesh = (DM_Plex *) dm->data; 1306 PetscInt off; 1307 PetscErrorCode ierr; 1308 1309 PetscFunctionBegin; 1310 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1311 #if defined(PETSC_USE_DEBUG) 1312 { 1313 PetscInt dof; 1314 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1315 if (dof) PetscValidPointer(coneOrientation, 3); 1316 } 1317 #endif 1318 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1319 *coneOrientation = &mesh->coneOrientations[off]; 1320 PetscFunctionReturn(0); 1321 } 1322 1323 #undef __FUNCT__ 1324 #define __FUNCT__ "DMPlexSetConeOrientation" 1325 /*@ 1326 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1327 1328 Not collective 1329 1330 Input Parameters: 1331 + mesh - The DMPlex 1332 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1333 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1334 integer giving the prescription for cone traversal. If it is negative, the cone is 1335 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1336 the index of the cone point on which to start. 1337 1338 Output Parameter: 1339 1340 Note: 1341 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1342 1343 Level: beginner 1344 1345 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1346 @*/ 1347 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1348 { 1349 DM_Plex *mesh = (DM_Plex *) dm->data; 1350 PetscInt pStart, pEnd; 1351 PetscInt dof, off, c; 1352 PetscErrorCode ierr; 1353 1354 PetscFunctionBegin; 1355 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1356 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1357 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1358 if (dof) PetscValidPointer(coneOrientation, 3); 1359 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1360 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); 1361 for (c = 0; c < dof; ++c) { 1362 PetscInt cdof, o = coneOrientation[c]; 1363 1364 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1365 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); 1366 mesh->coneOrientations[off+c] = o; 1367 } 1368 PetscFunctionReturn(0); 1369 } 1370 1371 #undef __FUNCT__ 1372 #define __FUNCT__ "DMPlexInsertCone" 1373 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1374 { 1375 DM_Plex *mesh = (DM_Plex *) dm->data; 1376 PetscInt pStart, pEnd; 1377 PetscInt dof, off; 1378 PetscErrorCode ierr; 1379 1380 PetscFunctionBegin; 1381 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1382 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1383 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1384 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1385 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); 1386 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); 1387 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); 1388 mesh->cones[off+conePos] = conePoint; 1389 PetscFunctionReturn(0); 1390 } 1391 1392 #undef __FUNCT__ 1393 #define __FUNCT__ "DMPlexGetSupportSize" 1394 /*@ 1395 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1396 1397 Not collective 1398 1399 Input Parameters: 1400 + mesh - The DMPlex 1401 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1402 1403 Output Parameter: 1404 . size - The support size for point p 1405 1406 Level: beginner 1407 1408 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1409 @*/ 1410 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1411 { 1412 DM_Plex *mesh = (DM_Plex *) dm->data; 1413 PetscErrorCode ierr; 1414 1415 PetscFunctionBegin; 1416 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1417 PetscValidPointer(size, 3); 1418 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1419 PetscFunctionReturn(0); 1420 } 1421 1422 #undef __FUNCT__ 1423 #define __FUNCT__ "DMPlexSetSupportSize" 1424 /*@ 1425 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1426 1427 Not collective 1428 1429 Input Parameters: 1430 + mesh - The DMPlex 1431 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1432 - size - The support size for point p 1433 1434 Output Parameter: 1435 1436 Note: 1437 This should be called after DMPlexSetChart(). 1438 1439 Level: beginner 1440 1441 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1442 @*/ 1443 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1444 { 1445 DM_Plex *mesh = (DM_Plex *) dm->data; 1446 PetscErrorCode ierr; 1447 1448 PetscFunctionBegin; 1449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1450 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1451 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1452 PetscFunctionReturn(0); 1453 } 1454 1455 #undef __FUNCT__ 1456 #define __FUNCT__ "DMPlexGetSupport" 1457 /*@C 1458 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1459 1460 Not collective 1461 1462 Input Parameters: 1463 + mesh - The DMPlex 1464 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1465 1466 Output Parameter: 1467 . support - An array of points which are on the out-edges for point p 1468 1469 Level: beginner 1470 1471 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1472 @*/ 1473 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1474 { 1475 DM_Plex *mesh = (DM_Plex *) dm->data; 1476 PetscInt off; 1477 PetscErrorCode ierr; 1478 1479 PetscFunctionBegin; 1480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1481 PetscValidPointer(support, 3); 1482 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1483 *support = &mesh->supports[off]; 1484 PetscFunctionReturn(0); 1485 } 1486 1487 #undef __FUNCT__ 1488 #define __FUNCT__ "DMPlexSetSupport" 1489 /*@ 1490 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1491 1492 Not collective 1493 1494 Input Parameters: 1495 + mesh - The DMPlex 1496 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1497 - support - An array of points which are on the in-edges for point p 1498 1499 Output Parameter: 1500 1501 Note: 1502 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1503 1504 Level: beginner 1505 1506 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1507 @*/ 1508 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1509 { 1510 DM_Plex *mesh = (DM_Plex *) dm->data; 1511 PetscInt pStart, pEnd; 1512 PetscInt dof, off, c; 1513 PetscErrorCode ierr; 1514 1515 PetscFunctionBegin; 1516 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1517 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1518 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1519 if (dof) PetscValidPointer(support, 3); 1520 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1521 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); 1522 for (c = 0; c < dof; ++c) { 1523 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); 1524 mesh->supports[off+c] = support[c]; 1525 } 1526 PetscFunctionReturn(0); 1527 } 1528 1529 #undef __FUNCT__ 1530 #define __FUNCT__ "DMPlexInsertSupport" 1531 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1532 { 1533 DM_Plex *mesh = (DM_Plex *) dm->data; 1534 PetscInt pStart, pEnd; 1535 PetscInt dof, off; 1536 PetscErrorCode ierr; 1537 1538 PetscFunctionBegin; 1539 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1540 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1541 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1542 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1543 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); 1544 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); 1545 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); 1546 mesh->supports[off+supportPos] = supportPoint; 1547 PetscFunctionReturn(0); 1548 } 1549 1550 #undef __FUNCT__ 1551 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1552 /*@C 1553 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1554 1555 Not collective 1556 1557 Input Parameters: 1558 + mesh - The DMPlex 1559 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1560 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1561 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1562 1563 Output Parameters: 1564 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1565 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1566 1567 Note: 1568 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1569 1570 Level: beginner 1571 1572 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1573 @*/ 1574 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1575 { 1576 DM_Plex *mesh = (DM_Plex *) dm->data; 1577 PetscInt *closure, *fifo; 1578 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1579 PetscInt tmpSize, t; 1580 PetscInt depth = 0, maxSize; 1581 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1582 PetscErrorCode ierr; 1583 1584 PetscFunctionBegin; 1585 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1586 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1587 maxSize = (PetscInt) (2*PetscMax(PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1), depth+1)); 1588 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1589 if (*points) { 1590 closure = *points; 1591 } else { 1592 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1593 } 1594 closure[0] = p; closure[1] = 0; 1595 /* This is only 1-level */ 1596 if (useCone) { 1597 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1598 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1599 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1600 } else { 1601 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1602 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1603 } 1604 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1605 const PetscInt cp = tmp[t]; 1606 const PetscInt co = tmpO ? tmpO[t] : 0; 1607 1608 closure[closureSize] = cp; 1609 closure[closureSize+1] = co; 1610 fifo[fifoSize] = cp; 1611 fifo[fifoSize+1] = co; 1612 } 1613 while(fifoSize - fifoStart) { 1614 const PetscInt q = fifo[fifoStart]; 1615 const PetscInt o = fifo[fifoStart+1]; 1616 const PetscInt rev = o >= 0 ? 0 : 1; 1617 const PetscInt off = rev ? -(o+1) : o; 1618 1619 if (useCone) { 1620 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1621 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1622 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1623 } else { 1624 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1625 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1626 tmpO = PETSC_NULL; 1627 } 1628 for (t = 0; t < tmpSize; ++t) { 1629 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1630 const PetscInt cp = tmp[i]; 1631 /* Must propogate orientation */ 1632 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1633 PetscInt c; 1634 1635 /* Check for duplicate */ 1636 for (c = 0; c < closureSize; c += 2) { 1637 if (closure[c] == cp) break; 1638 } 1639 if (c == closureSize) { 1640 closure[closureSize] = cp; 1641 closure[closureSize+1] = co; 1642 fifo[fifoSize] = cp; 1643 fifo[fifoSize+1] = co; 1644 closureSize += 2; 1645 fifoSize += 2; 1646 } 1647 } 1648 fifoStart += 2; 1649 } 1650 if (numPoints) *numPoints = closureSize/2; 1651 if (points) *points = closure; 1652 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1653 PetscFunctionReturn(0); 1654 } 1655 1656 #undef __FUNCT__ 1657 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1658 /*@C 1659 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1660 1661 Not collective 1662 1663 Input Parameters: 1664 + mesh - The DMPlex 1665 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1666 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1667 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1668 1669 Output Parameters: 1670 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1671 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1672 1673 Note: 1674 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1675 1676 Level: beginner 1677 1678 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1679 @*/ 1680 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1681 { 1682 PetscErrorCode ierr; 1683 1684 PetscFunctionBegin; 1685 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1686 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1687 PetscFunctionReturn(0); 1688 } 1689 1690 #undef __FUNCT__ 1691 #define __FUNCT__ "DMPlexGetFaces" 1692 /* 1693 DMPlexGetFaces - 1694 1695 Note: This will only work for cell-vertex meshes. 1696 */ 1697 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1698 { 1699 DM_Plex *mesh = (DM_Plex *) dm->data; 1700 const PetscInt *cone = PETSC_NULL; 1701 PetscInt depth = 0, dim, coneSize; 1702 PetscErrorCode ierr; 1703 1704 PetscFunctionBegin; 1705 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1706 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1707 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1708 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1709 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1710 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1711 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1712 switch(dim) { 1713 case 2: 1714 switch(coneSize) { 1715 case 3: 1716 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1717 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1718 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1719 *numFaces = 3; 1720 *faceSize = 2; 1721 *faces = mesh->facesTmp; 1722 break; 1723 case 4: 1724 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1725 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1726 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1727 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1728 *numFaces = 4; 1729 *faceSize = 2; 1730 *faces = mesh->facesTmp; 1731 break; 1732 default: 1733 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1734 } 1735 break; 1736 case 3: 1737 switch(coneSize) { 1738 case 3: 1739 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1740 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1741 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1742 *numFaces = 3; 1743 *faceSize = 2; 1744 *faces = mesh->facesTmp; 1745 break; 1746 case 4: 1747 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1748 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1749 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1750 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1751 *numFaces = 4; 1752 *faceSize = 3; 1753 *faces = mesh->facesTmp; 1754 break; 1755 default: 1756 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1757 } 1758 break; 1759 default: 1760 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1761 } 1762 PetscFunctionReturn(0); 1763 } 1764 1765 #undef __FUNCT__ 1766 #define __FUNCT__ "DMPlexGetMaxSizes" 1767 /*@ 1768 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1769 1770 Not collective 1771 1772 Input Parameter: 1773 . mesh - The DMPlex 1774 1775 Output Parameters: 1776 + maxConeSize - The maximum number of in-edges 1777 - maxSupportSize - The maximum number of out-edges 1778 1779 Level: beginner 1780 1781 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1782 @*/ 1783 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1784 { 1785 DM_Plex *mesh = (DM_Plex *) dm->data; 1786 1787 PetscFunctionBegin; 1788 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1789 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1790 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1791 PetscFunctionReturn(0); 1792 } 1793 1794 #undef __FUNCT__ 1795 #define __FUNCT__ "DMSetUp_Plex" 1796 PetscErrorCode DMSetUp_Plex(DM dm) 1797 { 1798 DM_Plex *mesh = (DM_Plex *) dm->data; 1799 PetscInt size; 1800 PetscErrorCode ierr; 1801 1802 PetscFunctionBegin; 1803 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1804 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1805 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1806 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1807 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1808 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1809 if (mesh->maxSupportSize) { 1810 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1811 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1812 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1813 } 1814 PetscFunctionReturn(0); 1815 } 1816 1817 #undef __FUNCT__ 1818 #define __FUNCT__ "DMCreateSubDM_Plex" 1819 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1820 { 1821 PetscSection section, sectionGlobal; 1822 PetscInt *subIndices; 1823 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1824 PetscErrorCode ierr; 1825 1826 PetscFunctionBegin; 1827 if (!numFields) PetscFunctionReturn(0); 1828 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1829 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1830 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1831 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1832 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1833 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); 1834 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1835 for (p = pStart; p < pEnd; ++p) { 1836 PetscInt gdof; 1837 1838 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1839 if (gdof > 0) { 1840 for (f = 0; f < numFields; ++f) { 1841 PetscInt fdof, fcdof; 1842 1843 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1844 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1845 subSize += fdof-fcdof; 1846 } 1847 } 1848 } 1849 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1850 for (p = pStart; p < pEnd; ++p) { 1851 PetscInt gdof, goff; 1852 1853 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1854 if (gdof > 0) { 1855 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1856 for (f = 0; f < numFields; ++f) { 1857 PetscInt fdof, fcdof, fc, f2, poff = 0; 1858 1859 /* Can get rid of this loop by storing field information in the global section */ 1860 for (f2 = 0; f2 < fields[f]; ++f2) { 1861 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1862 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1863 poff += fdof-fcdof; 1864 } 1865 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1866 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1867 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1868 subIndices[subOff] = goff+poff+fc; 1869 } 1870 } 1871 } 1872 } 1873 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1874 if (subdm) { 1875 PetscSection subsection; 1876 PetscBool haveNull = PETSC_FALSE; 1877 PetscInt f, nf = 0; 1878 1879 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1880 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1881 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1882 for (f = 0; f < numFields; ++f) { 1883 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1884 if ((*subdm)->nullspaceConstructors[f]) { 1885 haveNull = PETSC_TRUE; 1886 nf = f; 1887 } 1888 } 1889 if (haveNull) { 1890 MatNullSpace nullSpace; 1891 1892 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1893 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1894 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1895 } 1896 if (dm->fields) { 1897 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); 1898 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1899 for (f = 0; f < numFields; ++f) { 1900 ierr = PetscOListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist); 1901 } 1902 if (numFields == 1) { 1903 MatNullSpace space; 1904 Mat pmat; 1905 1906 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject *) &space);CHKERRQ(ierr); 1907 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1908 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject *) &space);CHKERRQ(ierr); 1909 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1910 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject *) &pmat);CHKERRQ(ierr); 1911 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1912 } 1913 } 1914 } 1915 PetscFunctionReturn(0); 1916 } 1917 1918 #undef __FUNCT__ 1919 #define __FUNCT__ "DMPlexSymmetrize" 1920 /*@ 1921 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1922 1923 Not collective 1924 1925 Input Parameter: 1926 . mesh - The DMPlex 1927 1928 Output Parameter: 1929 1930 Note: 1931 This should be called after all calls to DMPlexSetCone() 1932 1933 Level: beginner 1934 1935 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1936 @*/ 1937 PetscErrorCode DMPlexSymmetrize(DM dm) 1938 { 1939 DM_Plex *mesh = (DM_Plex *) dm->data; 1940 PetscInt *offsets; 1941 PetscInt supportSize; 1942 PetscInt pStart, pEnd, p; 1943 PetscErrorCode ierr; 1944 1945 PetscFunctionBegin; 1946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1947 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1948 /* Calculate support sizes */ 1949 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1950 for (p = pStart; p < pEnd; ++p) { 1951 PetscInt dof, off, c; 1952 1953 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1954 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1955 for (c = off; c < off+dof; ++c) { 1956 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1957 } 1958 } 1959 for (p = pStart; p < pEnd; ++p) { 1960 PetscInt dof; 1961 1962 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1963 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1964 } 1965 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1966 /* Calculate supports */ 1967 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1968 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1969 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1970 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1971 for (p = pStart; p < pEnd; ++p) { 1972 PetscInt dof, off, c; 1973 1974 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1975 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1976 for (c = off; c < off+dof; ++c) { 1977 const PetscInt q = mesh->cones[c]; 1978 PetscInt offS; 1979 1980 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1981 mesh->supports[offS+offsets[q]] = p; 1982 ++offsets[q]; 1983 } 1984 } 1985 ierr = PetscFree(offsets);CHKERRQ(ierr); 1986 PetscFunctionReturn(0); 1987 } 1988 1989 #undef __FUNCT__ 1990 #define __FUNCT__ "DMPlexSetDepth_Private" 1991 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1992 { 1993 PetscInt d; 1994 PetscErrorCode ierr; 1995 1996 PetscFunctionBegin; 1997 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1998 if (d < 0) { 1999 /* We are guaranteed that the point has a cone since the depth was not yet set */ 2000 const PetscInt *cone = PETSC_NULL; 2001 PetscInt dCone; 2002 2003 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2004 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2005 d = dCone+1; 2006 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2007 } 2008 *depth = d; 2009 PetscFunctionReturn(0); 2010 } 2011 2012 #undef __FUNCT__ 2013 #define __FUNCT__ "DMPlexStratify" 2014 /*@ 2015 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2016 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2017 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2018 the DAG. 2019 2020 Not collective 2021 2022 Input Parameter: 2023 . mesh - The DMPlex 2024 2025 Output Parameter: 2026 2027 Notes: 2028 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2029 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2030 2031 This should be called after all calls to DMPlexSymmetrize() 2032 2033 Level: beginner 2034 2035 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2036 @*/ 2037 PetscErrorCode DMPlexStratify(DM dm) 2038 { 2039 DM_Plex *mesh = (DM_Plex *) dm->data; 2040 PetscInt pStart, pEnd, p; 2041 PetscInt numRoots = 0, numLeaves = 0; 2042 PetscErrorCode ierr; 2043 2044 PetscFunctionBegin; 2045 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2046 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2047 /* Calculate depth */ 2048 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2049 /* Initialize roots and count leaves */ 2050 for (p = pStart; p < pEnd; ++p) { 2051 PetscInt coneSize, supportSize; 2052 2053 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2054 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2055 if (!coneSize && supportSize) { 2056 ++numRoots; 2057 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2058 } else if (!supportSize && coneSize) { 2059 ++numLeaves; 2060 } else if (!supportSize && !coneSize) { 2061 /* Isolated points */ 2062 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2063 } 2064 } 2065 if (numRoots + numLeaves == (pEnd - pStart)) { 2066 for (p = pStart; p < pEnd; ++p) { 2067 PetscInt coneSize, supportSize; 2068 2069 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2070 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2071 if (!supportSize && coneSize) { 2072 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2073 } 2074 } 2075 } else { 2076 /* This might be slow since lookup is not fast */ 2077 for (p = pStart; p < pEnd; ++p) { 2078 PetscInt depth; 2079 2080 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2081 } 2082 } 2083 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2084 PetscFunctionReturn(0); 2085 } 2086 2087 #undef __FUNCT__ 2088 #define __FUNCT__ "DMPlexGetJoin" 2089 /*@C 2090 DMPlexGetJoin - Get an array for the join of the set of points 2091 2092 Not Collective 2093 2094 Input Parameters: 2095 + dm - The DMPlex object 2096 . numPoints - The number of input points for the join 2097 - points - The input points 2098 2099 Output Parameters: 2100 + numCoveredPoints - The number of points in the join 2101 - coveredPoints - The points in the join 2102 2103 Level: intermediate 2104 2105 Note: Currently, this is restricted to a single level join 2106 2107 .keywords: mesh 2108 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2109 @*/ 2110 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2111 { 2112 DM_Plex *mesh = (DM_Plex *) dm->data; 2113 PetscInt *join[2]; 2114 PetscInt joinSize, i = 0; 2115 PetscInt dof, off, p, c, m; 2116 PetscErrorCode ierr; 2117 2118 PetscFunctionBegin; 2119 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2120 PetscValidPointer(points, 2); 2121 PetscValidPointer(numCoveredPoints, 3); 2122 PetscValidPointer(coveredPoints, 4); 2123 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2124 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2125 /* Copy in support of first point */ 2126 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2127 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2128 for (joinSize = 0; joinSize < dof; ++joinSize) { 2129 join[i][joinSize] = mesh->supports[off+joinSize]; 2130 } 2131 /* Check each successive support */ 2132 for (p = 1; p < numPoints; ++p) { 2133 PetscInt newJoinSize = 0; 2134 2135 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2136 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2137 for (c = 0; c < dof; ++c) { 2138 const PetscInt point = mesh->supports[off+c]; 2139 2140 for (m = 0; m < joinSize; ++m) { 2141 if (point == join[i][m]) { 2142 join[1-i][newJoinSize++] = point; 2143 break; 2144 } 2145 } 2146 } 2147 joinSize = newJoinSize; 2148 i = 1-i; 2149 } 2150 *numCoveredPoints = joinSize; 2151 *coveredPoints = join[i]; 2152 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2153 PetscFunctionReturn(0); 2154 } 2155 2156 #undef __FUNCT__ 2157 #define __FUNCT__ "DMPlexRestoreJoin" 2158 /*@C 2159 DMPlexRestoreJoin - Restore an array for the join of the set of points 2160 2161 Not Collective 2162 2163 Input Parameters: 2164 + dm - The DMPlex object 2165 . numPoints - The number of input points for the join 2166 - points - The input points 2167 2168 Output Parameters: 2169 + numCoveredPoints - The number of points in the join 2170 - coveredPoints - The points in the join 2171 2172 Level: intermediate 2173 2174 .keywords: mesh 2175 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2176 @*/ 2177 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2178 { 2179 PetscErrorCode ierr; 2180 2181 PetscFunctionBegin; 2182 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2183 PetscValidPointer(coveredPoints, 4); 2184 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2185 PetscFunctionReturn(0); 2186 } 2187 2188 #undef __FUNCT__ 2189 #define __FUNCT__ "DMPlexGetFullJoin" 2190 /*@C 2191 DMPlexGetFullJoin - Get an array for the join of the set of points 2192 2193 Not Collective 2194 2195 Input Parameters: 2196 + dm - The DMPlex object 2197 . numPoints - The number of input points for the join 2198 - points - The input points 2199 2200 Output Parameters: 2201 + numCoveredPoints - The number of points in the join 2202 - coveredPoints - The points in the join 2203 2204 Level: intermediate 2205 2206 .keywords: mesh 2207 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2208 @*/ 2209 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2210 { 2211 DM_Plex *mesh = (DM_Plex *) dm->data; 2212 PetscInt *offsets, **closures; 2213 PetscInt *join[2]; 2214 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2215 PetscInt p, d, c, m; 2216 PetscErrorCode ierr; 2217 2218 PetscFunctionBegin; 2219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2220 PetscValidPointer(points, 2); 2221 PetscValidPointer(numCoveredPoints, 3); 2222 PetscValidPointer(coveredPoints, 4); 2223 2224 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2225 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2226 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2227 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2228 maxSize = (PetscInt) (pow((PetscReal) mesh->maxSupportSize, depth)+1); 2229 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2230 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2231 2232 for (p = 0; p < numPoints; ++p) { 2233 PetscInt closureSize; 2234 2235 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2236 offsets[p*(depth+2)+0] = 0; 2237 for (d = 0; d < depth+1; ++d) { 2238 PetscInt pStart, pEnd, i; 2239 2240 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2241 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2242 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2243 offsets[p*(depth+2)+d+1] = i; 2244 break; 2245 } 2246 } 2247 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2248 } 2249 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); 2250 } 2251 for (d = 0; d < depth+1; ++d) { 2252 PetscInt dof; 2253 2254 /* Copy in support of first point */ 2255 dof = offsets[d+1] - offsets[d]; 2256 for (joinSize = 0; joinSize < dof; ++joinSize) { 2257 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2258 } 2259 /* Check each successive cone */ 2260 for (p = 1; p < numPoints && joinSize; ++p) { 2261 PetscInt newJoinSize = 0; 2262 2263 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2264 for (c = 0; c < dof; ++c) { 2265 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2266 2267 for (m = 0; m < joinSize; ++m) { 2268 if (point == join[i][m]) { 2269 join[1-i][newJoinSize++] = point; 2270 break; 2271 } 2272 } 2273 } 2274 joinSize = newJoinSize; 2275 i = 1-i; 2276 } 2277 if (joinSize) break; 2278 } 2279 *numCoveredPoints = joinSize; 2280 *coveredPoints = join[i]; 2281 for (p = 0; p < numPoints; ++p) { 2282 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2283 } 2284 ierr = PetscFree(closures);CHKERRQ(ierr); 2285 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2286 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2287 PetscFunctionReturn(0); 2288 } 2289 2290 #undef __FUNCT__ 2291 #define __FUNCT__ "DMPlexGetMeet" 2292 /*@C 2293 DMPlexGetMeet - Get an array for the meet of the set of points 2294 2295 Not Collective 2296 2297 Input Parameters: 2298 + dm - The DMPlex object 2299 . numPoints - The number of input points for the meet 2300 - points - The input points 2301 2302 Output Parameters: 2303 + numCoveredPoints - The number of points in the meet 2304 - coveredPoints - The points in the meet 2305 2306 Level: intermediate 2307 2308 Note: Currently, this is restricted to a single level meet 2309 2310 .keywords: mesh 2311 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2312 @*/ 2313 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2314 { 2315 DM_Plex *mesh = (DM_Plex *) dm->data; 2316 PetscInt *meet[2]; 2317 PetscInt meetSize, i = 0; 2318 PetscInt dof, off, p, c, m; 2319 PetscErrorCode ierr; 2320 2321 PetscFunctionBegin; 2322 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2323 PetscValidPointer(points, 2); 2324 PetscValidPointer(numCoveringPoints, 3); 2325 PetscValidPointer(coveringPoints, 4); 2326 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2327 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2328 /* Copy in cone of first point */ 2329 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2330 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2331 for (meetSize = 0; meetSize < dof; ++meetSize) { 2332 meet[i][meetSize] = mesh->cones[off+meetSize]; 2333 } 2334 /* Check each successive cone */ 2335 for (p = 1; p < numPoints; ++p) { 2336 PetscInt newMeetSize = 0; 2337 2338 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2339 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2340 for (c = 0; c < dof; ++c) { 2341 const PetscInt point = mesh->cones[off+c]; 2342 2343 for (m = 0; m < meetSize; ++m) { 2344 if (point == meet[i][m]) { 2345 meet[1-i][newMeetSize++] = point; 2346 break; 2347 } 2348 } 2349 } 2350 meetSize = newMeetSize; 2351 i = 1-i; 2352 } 2353 *numCoveringPoints = meetSize; 2354 *coveringPoints = meet[i]; 2355 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2356 PetscFunctionReturn(0); 2357 } 2358 2359 #undef __FUNCT__ 2360 #define __FUNCT__ "DMPlexRestoreMeet" 2361 /*@C 2362 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2363 2364 Not Collective 2365 2366 Input Parameters: 2367 + dm - The DMPlex object 2368 . numPoints - The number of input points for the meet 2369 - points - The input points 2370 2371 Output Parameters: 2372 + numCoveredPoints - The number of points in the meet 2373 - coveredPoints - The points in the meet 2374 2375 Level: intermediate 2376 2377 .keywords: mesh 2378 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2379 @*/ 2380 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2381 { 2382 PetscErrorCode ierr; 2383 2384 PetscFunctionBegin; 2385 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2386 PetscValidPointer(coveredPoints, 4); 2387 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2388 PetscFunctionReturn(0); 2389 } 2390 2391 #undef __FUNCT__ 2392 #define __FUNCT__ "DMPlexGetFullMeet" 2393 /*@C 2394 DMPlexGetFullMeet - Get an array for the meet of the set of points 2395 2396 Not Collective 2397 2398 Input Parameters: 2399 + dm - The DMPlex object 2400 . numPoints - The number of input points for the meet 2401 - points - The input points 2402 2403 Output Parameters: 2404 + numCoveredPoints - The number of points in the meet 2405 - coveredPoints - The points in the meet 2406 2407 Level: intermediate 2408 2409 .keywords: mesh 2410 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2411 @*/ 2412 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2413 { 2414 DM_Plex *mesh = (DM_Plex *) dm->data; 2415 PetscInt *offsets, **closures; 2416 PetscInt *meet[2]; 2417 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2418 PetscInt p, h, c, m; 2419 PetscErrorCode ierr; 2420 2421 PetscFunctionBegin; 2422 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2423 PetscValidPointer(points, 2); 2424 PetscValidPointer(numCoveredPoints, 3); 2425 PetscValidPointer(coveredPoints, 4); 2426 2427 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2428 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2429 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2430 maxSize = (PetscInt) (pow((PetscReal) mesh->maxConeSize, height)+1); 2431 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2432 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2433 2434 for (p = 0; p < numPoints; ++p) { 2435 PetscInt closureSize; 2436 2437 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2438 offsets[p*(height+2)+0] = 0; 2439 for (h = 0; h < height+1; ++h) { 2440 PetscInt pStart, pEnd, i; 2441 2442 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2443 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2444 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2445 offsets[p*(height+2)+h+1] = i; 2446 break; 2447 } 2448 } 2449 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2450 } 2451 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); 2452 } 2453 for (h = 0; h < height+1; ++h) { 2454 PetscInt dof; 2455 2456 /* Copy in cone of first point */ 2457 dof = offsets[h+1] - offsets[h]; 2458 for (meetSize = 0; meetSize < dof; ++meetSize) { 2459 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2460 } 2461 /* Check each successive cone */ 2462 for (p = 1; p < numPoints && meetSize; ++p) { 2463 PetscInt newMeetSize = 0; 2464 2465 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2466 for (c = 0; c < dof; ++c) { 2467 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2468 2469 for (m = 0; m < meetSize; ++m) { 2470 if (point == meet[i][m]) { 2471 meet[1-i][newMeetSize++] = point; 2472 break; 2473 } 2474 } 2475 } 2476 meetSize = newMeetSize; 2477 i = 1-i; 2478 } 2479 if (meetSize) break; 2480 } 2481 *numCoveredPoints = meetSize; 2482 *coveredPoints = meet[i]; 2483 for (p = 0; p < numPoints; ++p) { 2484 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2485 } 2486 ierr = PetscFree(closures);CHKERRQ(ierr); 2487 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2488 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2489 PetscFunctionReturn(0); 2490 } 2491 2492 #undef __FUNCT__ 2493 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2494 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) { 2495 MPI_Comm comm = ((PetscObject) dm)->comm; 2496 PetscInt cellDim; 2497 PetscErrorCode ierr; 2498 2499 PetscFunctionBegin; 2500 PetscValidPointer(numFaceVertices,3); 2501 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2502 switch(cellDim) { 2503 case 0: 2504 *numFaceVertices = 0; 2505 break; 2506 case 1: 2507 *numFaceVertices = 1; 2508 break; 2509 case 2: 2510 switch(numCorners) { 2511 case 3: // triangle 2512 *numFaceVertices = 2; // Edge has 2 vertices 2513 break; 2514 case 4: // quadrilateral 2515 *numFaceVertices = 2; // Edge has 2 vertices 2516 break; 2517 case 6: // quadratic triangle, tri and quad cohesive Lagrange cells 2518 *numFaceVertices = 3; // Edge has 3 vertices 2519 break; 2520 case 9: // quadratic quadrilateral, quadratic quad cohesive Lagrange cells 2521 *numFaceVertices = 3; // Edge has 3 vertices 2522 break; 2523 default: 2524 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2525 } 2526 break; 2527 case 3: 2528 switch(numCorners) { 2529 case 4: // tetradehdron 2530 *numFaceVertices = 3; // Face has 3 vertices 2531 break; 2532 case 6: // tet cohesive cells 2533 *numFaceVertices = 4; // Face has 4 vertices 2534 break; 2535 case 8: // hexahedron 2536 *numFaceVertices = 4; // Face has 4 vertices 2537 break; 2538 case 9: // tet cohesive Lagrange cells 2539 *numFaceVertices = 6; // Face has 6 vertices 2540 break; 2541 case 10: // quadratic tetrahedron 2542 *numFaceVertices = 6; // Face has 6 vertices 2543 break; 2544 case 12: // hex cohesive Lagrange cells 2545 *numFaceVertices = 6; // Face has 6 vertices 2546 break; 2547 case 18: // quadratic tet cohesive Lagrange cells 2548 *numFaceVertices = 6; // Face has 6 vertices 2549 break; 2550 case 27: // quadratic hexahedron, quadratic hex cohesive Lagrange cells 2551 *numFaceVertices = 9; // Face has 9 vertices 2552 break; 2553 default: 2554 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2555 } 2556 break; 2557 default: 2558 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2559 } 2560 PetscFunctionReturn(0); 2561 } 2562 2563 #undef __FUNCT__ 2564 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2565 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) { 2566 const PetscInt maxFaceCases = 30; 2567 PetscInt numFaceCases = 0; 2568 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2569 PetscInt *off, *adj; 2570 PetscInt *neighborCells, *tmpClosure; 2571 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2572 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2573 PetscErrorCode ierr; 2574 2575 PetscFunctionBegin; 2576 /* For parallel partitioning, I think you have to communicate supports */ 2577 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2578 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2579 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2580 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2581 if (cEnd - cStart == 0) { 2582 if (numVertices) *numVertices = 0; 2583 if (offsets) *offsets = PETSC_NULL; 2584 if (adjacency) *adjacency = PETSC_NULL; 2585 PetscFunctionReturn(0); 2586 } 2587 numCells = cEnd - cStart; 2588 /* Setup face recognition */ 2589 { 2590 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 */ 2591 2592 for (c = cStart; c < cEnd; ++c) { 2593 PetscInt corners; 2594 2595 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2596 if (!cornersSeen[corners]) { 2597 PetscInt nFV; 2598 2599 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2600 cornersSeen[corners] = 1; 2601 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2602 numFaceVertices[numFaceCases++] = nFV; 2603 } 2604 } 2605 } 2606 maxClosure = (PetscInt) (2*PetscMax(pow((PetscReal) maxConeSize, depth)+1, pow((PetscReal) maxSupportSize, depth)+1)); 2607 maxNeighbors = (PetscInt) (pow((PetscReal) maxConeSize, depth)*pow((PetscReal) maxSupportSize, depth)+1); 2608 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2609 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2610 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2611 /* Count neighboring cells */ 2612 for (cell = cStart; cell < cEnd; ++cell) { 2613 PetscInt numNeighbors = maxNeighbors, n; 2614 2615 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2616 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2617 for (n = 0; n < numNeighbors; ++n) { 2618 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2619 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2620 PetscInt meetSize = 0; 2621 const PetscInt *meet = PETSC_NULL; 2622 2623 if (cellPair[0] == cellPair[1]) continue; 2624 if (!found) { 2625 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2626 if (meetSize) { 2627 PetscInt f; 2628 2629 for (f = 0; f < numFaceCases; ++f) { 2630 if (numFaceVertices[f] == meetSize) { 2631 found = PETSC_TRUE; 2632 break; 2633 } 2634 } 2635 } 2636 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2637 } 2638 if (found) { 2639 ++off[cell-cStart+1]; 2640 } 2641 } 2642 } 2643 /* Prefix sum */ 2644 for (cell = 1; cell <= numCells; ++cell) { 2645 off[cell] += off[cell-1]; 2646 } 2647 if (adjacency) { 2648 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2649 /* Get neighboring cells */ 2650 for (cell = cStart; cell < cEnd; ++cell) { 2651 PetscInt numNeighbors = maxNeighbors, n; 2652 PetscInt cellOffset = 0; 2653 2654 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2655 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2656 for (n = 0; n < numNeighbors; ++n) { 2657 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2658 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2659 PetscInt meetSize = 0; 2660 const PetscInt *meet = PETSC_NULL; 2661 2662 if (cellPair[0] == cellPair[1]) continue; 2663 if (!found) { 2664 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2665 if (meetSize) { 2666 PetscInt f; 2667 2668 for (f = 0; f < numFaceCases; ++f) { 2669 if (numFaceVertices[f] == meetSize) { 2670 found = PETSC_TRUE; 2671 break; 2672 } 2673 } 2674 } 2675 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2676 } 2677 if (found) { 2678 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2679 ++cellOffset; 2680 } 2681 } 2682 } 2683 } 2684 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2685 if (numVertices) *numVertices = numCells; 2686 if (offsets) *offsets = off; 2687 if (adjacency) *adjacency = adj; 2688 PetscFunctionReturn(0); 2689 } 2690 2691 #ifdef PETSC_HAVE_CHACO 2692 #ifdef PETSC_HAVE_UNISTD_H 2693 #include <unistd.h> 2694 #endif 2695 /* Chaco does not have an include file */ 2696 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2697 float *ewgts, float *x, float *y, float *z, char *outassignname, 2698 char *outfilename, short *assignment, int architecture, int ndims_tot, 2699 int mesh_dims[3], double *goal, int global_method, int local_method, 2700 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2701 2702 extern int FREE_GRAPH; 2703 2704 #undef __FUNCT__ 2705 #define __FUNCT__ "DMPlexPartition_Chaco" 2706 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2707 { 2708 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2709 MPI_Comm comm = ((PetscObject) dm)->comm; 2710 int nvtxs = numVertices; /* number of vertices in full graph */ 2711 int *vwgts = NULL; /* weights for all vertices */ 2712 float *ewgts = NULL; /* weights for all edges */ 2713 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2714 char *outassignname = NULL; /* name of assignment output file */ 2715 char *outfilename = NULL; /* output file name */ 2716 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2717 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2718 int mesh_dims[3]; /* dimensions of mesh of processors */ 2719 double *goal = NULL; /* desired set sizes for each set */ 2720 int global_method = 1; /* global partitioning algorithm */ 2721 int local_method = 1; /* local partitioning algorithm */ 2722 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2723 int vmax = 200; /* how many vertices to coarsen down to? */ 2724 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2725 double eigtol = 0.001; /* tolerance on eigenvectors */ 2726 long seed = 123636512; /* for random graph mutations */ 2727 short int *assignment; /* Output partition */ 2728 int fd_stdout, fd_pipe[2]; 2729 PetscInt *points; 2730 PetscMPIInt commSize; 2731 int i, v, p; 2732 PetscErrorCode ierr; 2733 2734 PetscFunctionBegin; 2735 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2736 if (!numVertices) { 2737 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2738 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2739 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2740 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2741 PetscFunctionReturn(0); 2742 } 2743 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2744 for (i = 0; i < start[numVertices]; ++i) { 2745 ++adjacency[i]; 2746 } 2747 if (global_method == INERTIAL_METHOD) { 2748 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2749 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2750 } 2751 mesh_dims[0] = commSize; 2752 mesh_dims[1] = 1; 2753 mesh_dims[2] = 1; 2754 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2755 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2756 /* TODO: check error codes for UNIX calls */ 2757 #ifdef PETSC_HAVE_UNISTD_H 2758 { 2759 fd_stdout = dup(1); 2760 pipe(fd_pipe); 2761 close(1); 2762 dup2(fd_pipe[1], 1); 2763 } 2764 #endif 2765 ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2766 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2767 vmax, ndims, eigtol, seed); 2768 #ifdef PETSC_HAVE_UNISTD_H 2769 { 2770 char msgLog[10000]; 2771 int count; 2772 2773 fflush(stdout); 2774 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2775 if (count < 0) count = 0; 2776 msgLog[count] = 0; 2777 close(1); 2778 dup2(fd_stdout, 1); 2779 close(fd_stdout); 2780 close(fd_pipe[0]); 2781 close(fd_pipe[1]); 2782 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2783 } 2784 #endif 2785 /* Convert to PetscSection+IS */ 2786 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2787 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2788 for (v = 0; v < nvtxs; ++v) { 2789 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2790 } 2791 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2792 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2793 for (p = 0, i = 0; p < commSize; ++p) { 2794 for (v = 0; v < nvtxs; ++v) { 2795 if (assignment[v] == p) points[i++] = v; 2796 } 2797 } 2798 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2799 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2800 if (global_method == INERTIAL_METHOD) { 2801 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2802 } 2803 ierr = PetscFree(assignment);CHKERRQ(ierr); 2804 for (i = 0; i < start[numVertices]; ++i) { 2805 --adjacency[i]; 2806 } 2807 PetscFunctionReturn(0); 2808 } 2809 #endif 2810 2811 #ifdef PETSC_HAVE_PARMETIS 2812 #undef __FUNCT__ 2813 #define __FUNCT__ "DMPlexPartition_ParMetis" 2814 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2815 { 2816 PetscFunctionBegin; 2817 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2818 PetscFunctionReturn(0); 2819 } 2820 #endif 2821 2822 #undef __FUNCT__ 2823 #define __FUNCT__ "DMPlexEnlargePartition" 2824 /* Expand the partition by BFS on the adjacency graph */ 2825 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) { 2826 PetscHashI h; 2827 const PetscInt *points; 2828 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2829 PetscInt pStart, pEnd, part, q; 2830 PetscErrorCode ierr; 2831 2832 PetscFunctionBegin; 2833 PetscHashICreate(h); 2834 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2835 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2836 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2837 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2838 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2839 for(part = pStart; part < pEnd; ++part) { 2840 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2841 2842 PetscHashIClear(h); 2843 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2844 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2845 /* Add all existing points to h */ 2846 for(p = 0; p < numPoints; ++p) { 2847 const PetscInt point = points[off+p]; 2848 PetscHashIAdd(h, point, 1); 2849 } 2850 PetscHashISize(h, nP); 2851 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2852 /* Add all points in next BFS level */ 2853 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2854 for(p = 0; p < numPoints; ++p) { 2855 const PetscInt point = points[off+p]; 2856 PetscInt s = start[point], e = start[point+1], a; 2857 2858 for(a = s; a < e; ++a) { 2859 PetscHashIAdd(h, adjacency[a], 1); 2860 } 2861 } 2862 PetscHashISize(h, numNewPoints); 2863 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2864 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2865 if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2866 totPoints += numNewPoints; 2867 } 2868 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2869 PetscHashIDestroy(h); 2870 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2871 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2872 for(part = pStart, q = 0; part < pEnd; ++part) { 2873 PetscInt numPoints, p; 2874 2875 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2876 for(p = 0; p < numPoints; ++p, ++q) { 2877 newPoints[q] = tmpPoints[part][p]; 2878 } 2879 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2880 } 2881 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2882 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2883 PetscFunctionReturn(0); 2884 } 2885 2886 #undef __FUNCT__ 2887 #define __FUNCT__ "DMPlexCreatePartition" 2888 /* 2889 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2890 2891 Collective on DM 2892 2893 Input Parameters: 2894 + dm - The DM 2895 . height - The height for points in the partition 2896 - enlarge - Expand each partition with neighbors 2897 2898 Output Parameters: 2899 + partSection - The PetscSection giving the division of points by partition 2900 . partition - The list of points by partition 2901 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2902 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2903 2904 Level: developer 2905 2906 .seealso DMPlexDistribute() 2907 */ 2908 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) { 2909 PetscMPIInt size; 2910 PetscErrorCode ierr; 2911 2912 PetscFunctionBegin; 2913 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2914 *origPartSection = PETSC_NULL; 2915 *origPartition = PETSC_NULL; 2916 if (size == 1) { 2917 PetscInt *points; 2918 PetscInt cStart, cEnd, c; 2919 2920 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2921 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2922 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2923 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2924 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2925 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2926 for (c = cStart; c < cEnd; ++c) { 2927 points[c] = c; 2928 } 2929 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2930 PetscFunctionReturn(0); 2931 } 2932 if (height == 0) { 2933 PetscInt numVertices; 2934 PetscInt *start = PETSC_NULL; 2935 PetscInt *adjacency = PETSC_NULL; 2936 2937 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2938 if (1) { 2939 #ifdef PETSC_HAVE_CHACO 2940 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2941 #endif 2942 } else { 2943 #ifdef PETSC_HAVE_PARMETIS 2944 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2945 #endif 2946 } 2947 if (enlarge) { 2948 *origPartSection = *partSection; 2949 *origPartition = *partition; 2950 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2951 } 2952 ierr = PetscFree(start);CHKERRQ(ierr); 2953 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2954 # if 0 2955 } else if (height == 1) { 2956 /* Build the dual graph for faces and partition the hypergraph */ 2957 PetscInt numEdges; 2958 2959 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2960 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2961 destroyCSR(numEdges, start, adjacency); 2962 #endif 2963 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2964 PetscFunctionReturn(0); 2965 } 2966 2967 #undef __FUNCT__ 2968 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2969 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) { 2970 /* const PetscInt height = 0; */ 2971 const PetscInt *partArray; 2972 PetscInt *allPoints, *partPoints = PETSC_NULL; 2973 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2974 PetscErrorCode ierr; 2975 2976 PetscFunctionBegin; 2977 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2978 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2979 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2980 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2981 for (rank = rStart; rank < rEnd; ++rank) { 2982 PetscInt partSize = 0; 2983 PetscInt numPoints, offset, p; 2984 2985 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2986 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2987 for (p = 0; p < numPoints; ++p) { 2988 PetscInt point = partArray[offset+p], closureSize, c; 2989 PetscInt *closure = PETSC_NULL; 2990 2991 /* TODO Include support for height > 0 case */ 2992 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2993 /* Merge into existing points */ 2994 if (partSize+closureSize > maxPartSize) { 2995 PetscInt *tmpPoints; 2996 2997 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2998 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2999 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3000 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3001 partPoints = tmpPoints; 3002 } 3003 for (c = 0; c < closureSize; ++c) { 3004 partPoints[partSize+c] = closure[c*2]; 3005 } 3006 partSize += closureSize; 3007 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3008 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3009 } 3010 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3011 } 3012 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3013 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3014 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3015 3016 for (rank = rStart; rank < rEnd; ++rank) { 3017 PetscInt partSize = 0, newOffset; 3018 PetscInt numPoints, offset, p; 3019 3020 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3021 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3022 for (p = 0; p < numPoints; ++p) { 3023 PetscInt point = partArray[offset+p], closureSize, c; 3024 PetscInt *closure = PETSC_NULL; 3025 3026 /* TODO Include support for height > 0 case */ 3027 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3028 /* Merge into existing points */ 3029 for (c = 0; c < closureSize; ++c) { 3030 partPoints[partSize+c] = closure[c*2]; 3031 } 3032 partSize += closureSize; 3033 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3034 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3035 } 3036 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3037 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3038 } 3039 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3040 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3041 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3042 PetscFunctionReturn(0); 3043 } 3044 3045 #undef __FUNCT__ 3046 #define __FUNCT__ "DMPlexDistributeField" 3047 /* 3048 Input Parameters: 3049 . originalSection 3050 , originalVec 3051 3052 Output Parameters: 3053 . newSection 3054 . newVec 3055 */ 3056 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3057 { 3058 PetscSF fieldSF; 3059 PetscInt *remoteOffsets, fieldSize; 3060 PetscScalar *originalValues, *newValues; 3061 PetscErrorCode ierr; 3062 3063 PetscFunctionBegin; 3064 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3065 3066 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3067 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3068 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3069 3070 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3071 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3072 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3073 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3074 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3075 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3076 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3077 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3078 PetscFunctionReturn(0); 3079 } 3080 3081 #undef __FUNCT__ 3082 #define __FUNCT__ "DMPlexDistribute" 3083 /*@C 3084 DMPlexDistribute - Distributes the mesh and any associated sections. 3085 3086 Not Collective 3087 3088 Input Parameter: 3089 + dm - The original DMPlex object 3090 . partitioner - The partitioning package, or NULL for the default 3091 - overlap - The overlap of partitions, 0 is the default 3092 3093 Output Parameter: 3094 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3095 3096 Note: If the mesh was not distributed, the return value is PETSC_NULL 3097 3098 Level: intermediate 3099 3100 .keywords: mesh, elements 3101 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3102 @*/ 3103 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3104 { 3105 DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3106 MPI_Comm comm = ((PetscObject) dm)->comm; 3107 const PetscInt height = 0; 3108 PetscInt dim, numRemoteRanks; 3109 IS origCellPart, cellPart, part; 3110 PetscSection origCellPartSection, cellPartSection, partSection; 3111 PetscSFNode *remoteRanks; 3112 PetscSF partSF, pointSF, coneSF; 3113 ISLocalToGlobalMapping renumbering; 3114 PetscSection originalConeSection, newConeSection; 3115 PetscInt *remoteOffsets; 3116 PetscInt *cones, *newCones, newConesSize; 3117 PetscBool flg; 3118 PetscMPIInt rank, numProcs, p; 3119 PetscErrorCode ierr; 3120 3121 PetscFunctionBegin; 3122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3123 PetscValidPointer(dmParallel,4); 3124 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3125 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3126 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3127 *dmParallel = PETSC_NULL; 3128 if (numProcs == 1) PetscFunctionReturn(0); 3129 3130 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3131 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3132 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3133 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3134 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3135 if (!rank) { 3136 numRemoteRanks = numProcs; 3137 } else { 3138 numRemoteRanks = 0; 3139 } 3140 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3141 for (p = 0; p < numRemoteRanks; ++p) { 3142 remoteRanks[p].rank = p; 3143 remoteRanks[p].index = 0; 3144 } 3145 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3146 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3147 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3148 if (flg) { 3149 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3150 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3151 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3152 if (origCellPart) { 3153 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3154 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3155 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3156 } 3157 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3158 } 3159 /* Close the partition over the mesh */ 3160 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3161 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3162 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3163 /* Create new mesh */ 3164 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3165 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3166 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3167 pmesh = (DM_Plex *) (*dmParallel)->data; 3168 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3169 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3170 if (flg) { 3171 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3172 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3173 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3174 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3175 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3176 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3177 } 3178 /* Distribute cone section */ 3179 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3180 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3181 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3182 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3183 { 3184 PetscInt pStart, pEnd, p; 3185 3186 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3187 for (p = pStart; p < pEnd; ++p) { 3188 PetscInt coneSize; 3189 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3190 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3191 } 3192 } 3193 /* Communicate and renumber cones */ 3194 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3195 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3196 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3197 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3198 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3199 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3200 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3201 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3202 if (flg) { 3203 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3204 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3205 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3206 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3207 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3208 } 3209 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3210 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3211 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3212 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3213 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3214 /* Create supports and stratify sieve */ 3215 { 3216 PetscInt pStart, pEnd; 3217 3218 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3219 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3220 } 3221 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3222 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3223 /* Distribute Coordinates */ 3224 { 3225 PetscSection originalCoordSection, newCoordSection; 3226 Vec originalCoordinates, newCoordinates; 3227 const char *name; 3228 3229 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3230 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3231 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3232 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3233 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3234 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3235 3236 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3237 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3238 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3239 } 3240 /* Distribute labels */ 3241 { 3242 DMLabel next = mesh->labels, newNext = pmesh->labels; 3243 PetscInt numLabels = 0, l; 3244 3245 /* Bcast number of labels */ 3246 while(next) {++numLabels; next = next->next;} 3247 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3248 next = mesh->labels; 3249 for (l = 0; l < numLabels; ++l) { 3250 DMLabel newLabel; 3251 const PetscInt *partArray; 3252 char *name; 3253 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3254 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3255 PetscInt nameSize, s, p; 3256 PetscBool isdepth; 3257 size_t len = 0; 3258 3259 /* Bcast name (could filter for no points) */ 3260 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3261 nameSize = len; 3262 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3263 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3264 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3265 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3266 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3267 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3268 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3269 newLabel->name = name; 3270 /* Bcast numStrata (could filter for no points in stratum) */ 3271 if (!rank) {newLabel->numStrata = next->numStrata;} 3272 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3273 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3274 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3275 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3276 /* Bcast stratumValues (could filter for no points in stratum) */ 3277 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3278 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3279 /* Find size on each process and Scatter */ 3280 if (!rank) { 3281 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3282 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3283 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3284 for (s = 0; s < next->numStrata; ++s) { 3285 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3286 const PetscInt point = next->points[p]; 3287 PetscInt proc; 3288 3289 for (proc = 0; proc < numProcs; ++proc) { 3290 PetscInt dof, off, pPart; 3291 3292 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3293 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3294 for (pPart = off; pPart < off+dof; ++pPart) { 3295 if (partArray[pPart] == point) { 3296 ++stratumSizes[proc*next->numStrata+s]; 3297 break; 3298 } 3299 } 3300 } 3301 } 3302 } 3303 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3304 } 3305 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3306 /* Calculate stratumOffsets */ 3307 newLabel->stratumOffsets[0] = 0; 3308 for (s = 0; s < newLabel->numStrata; ++s) { 3309 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3310 } 3311 /* Pack points and Scatter */ 3312 if (!rank) { 3313 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3314 displs[0] = 0; 3315 for (p = 0; p < numProcs; ++p) { 3316 sendcnts[p] = 0; 3317 for (s = 0; s < next->numStrata; ++s) { 3318 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3319 } 3320 offsets[p] = displs[p]; 3321 displs[p+1] = displs[p] + sendcnts[p]; 3322 } 3323 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3324 for (s = 0; s < next->numStrata; ++s) { 3325 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3326 const PetscInt point = next->points[p]; 3327 PetscInt proc; 3328 3329 for (proc = 0; proc < numProcs; ++proc) { 3330 PetscInt dof, off, pPart; 3331 3332 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3333 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3334 for (pPart = off; pPart < off+dof; ++pPart) { 3335 if (partArray[pPart] == point) { 3336 points[offsets[proc]++] = point; 3337 break; 3338 } 3339 } 3340 } 3341 } 3342 } 3343 } 3344 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3345 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3346 ierr = PetscFree(points);CHKERRQ(ierr); 3347 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3348 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3349 /* Renumber points */ 3350 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3351 /* Sort points */ 3352 for (s = 0; s < newLabel->numStrata; ++s) { 3353 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3354 } 3355 /* Insert into list */ 3356 if (newNext) { 3357 newNext->next = newLabel; 3358 } else { 3359 pmesh->labels = newLabel; 3360 } 3361 newNext = newLabel; 3362 if (!rank) {next = next->next;} 3363 } 3364 } 3365 /* Cleanup Partition */ 3366 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3367 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3368 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3369 ierr = ISDestroy(&part);CHKERRQ(ierr); 3370 /* Create point SF for parallel mesh */ 3371 { 3372 const PetscInt *leaves; 3373 PetscSFNode *remotePoints, *rowners, *lowners; 3374 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3375 PetscInt pStart, pEnd; 3376 3377 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3378 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3379 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3380 for (p=0; p<numRoots; p++) { 3381 rowners[p].rank = -1; 3382 rowners[p].index = -1; 3383 } 3384 if (origCellPart) { 3385 /* Make sure cells in the original partition are not assigned to other procs */ 3386 const PetscInt *origCells; 3387 3388 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3389 for (p = 0; p < numProcs; ++p) { 3390 PetscInt dof, off, d; 3391 3392 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3393 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3394 for(d = off; d < off+dof; ++d) { 3395 rowners[origCells[d]].rank = p; 3396 } 3397 } 3398 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3399 } 3400 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3401 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3402 3403 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3404 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3405 for (p = 0; p < numLeaves; ++p) { 3406 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3407 lowners[p].rank = rank; 3408 lowners[p].index = leaves ? leaves[p] : p; 3409 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3410 lowners[p].rank = -2; 3411 lowners[p].index = -2; 3412 } 3413 } 3414 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3415 rowners[p].rank = -3; 3416 rowners[p].index = -3; 3417 } 3418 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3419 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3420 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3421 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3422 for (p = 0; p < numLeaves; ++p) { 3423 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3424 if (lowners[p].rank != rank) ++numGhostPoints; 3425 } 3426 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3427 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3428 for (p = 0, gp = 0; p < numLeaves; ++p) { 3429 if (lowners[p].rank != rank) { 3430 ghostPoints[gp] = leaves ? leaves[p] : p; 3431 remotePoints[gp].rank = lowners[p].rank; 3432 remotePoints[gp].index = lowners[p].index; 3433 ++gp; 3434 } 3435 } 3436 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3437 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3438 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3439 } 3440 /* Cleanup */ 3441 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3442 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3443 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3444 PetscFunctionReturn(0); 3445 } 3446 3447 #undef __FUNCT__ 3448 #define __FUNCT__ "DMPlexRenumber_Private" 3449 /* 3450 Reasons to renumber: 3451 3452 1) Permute points, e.g. bandwidth reduction (Renumber) 3453 3454 a) Must not mix strata 3455 3456 2) Shift numbers for point insertion (Shift) 3457 3458 a) Want operation brken into parts so that insertion can be interleaved 3459 3460 renumbering - An IS which provides the new numbering 3461 */ 3462 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3463 { 3464 PetscFunctionBegin; 3465 PetscFunctionReturn(0); 3466 } 3467 3468 #undef __FUNCT__ 3469 #define __FUNCT__ "DMPlexShiftPoint_Private" 3470 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3471 { 3472 if (depth < 0) return p; 3473 /* Cells */ if (p < depthEnd[depth]) return p; 3474 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3475 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3476 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3477 } 3478 3479 #undef __FUNCT__ 3480 #define __FUNCT__ "DMPlexShiftSizes_Private" 3481 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3482 { 3483 PetscInt *depthEnd; 3484 PetscInt depth = 0, d, pStart, pEnd, p; 3485 PetscErrorCode ierr; 3486 3487 PetscFunctionBegin; 3488 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3489 if (depth < 0) PetscFunctionReturn(0); 3490 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3491 /* Step 1: Expand chart */ 3492 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3493 for(d = 0; d <= depth; ++d) { 3494 pEnd += depthShift[d]; 3495 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3496 } 3497 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3498 /* Step 2: Set cone and support sizes */ 3499 for(d = 0; d <= depth; ++d) { 3500 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3501 for(p = pStart; p < pEnd; ++p) { 3502 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3503 PetscInt size; 3504 3505 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3506 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3507 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3508 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3509 } 3510 } 3511 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3512 PetscFunctionReturn(0); 3513 } 3514 3515 #undef __FUNCT__ 3516 #define __FUNCT__ "DMPlexShiftPoints_Private" 3517 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3518 { 3519 PetscInt *depthEnd, *newpoints; 3520 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3521 PetscErrorCode ierr; 3522 3523 PetscFunctionBegin; 3524 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3525 if (depth < 0) PetscFunctionReturn(0); 3526 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3527 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3528 for(d = 0; d <= depth; ++d) { 3529 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3530 } 3531 /* Step 5: Set cones and supports */ 3532 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3533 for(p = pStart; p < pEnd; ++p) { 3534 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3535 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3536 3537 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3538 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3539 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3540 for(i = 0; i < size; ++i) { 3541 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3542 } 3543 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3544 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3545 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3546 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3547 for(i = 0; i < size; ++i) { 3548 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3549 } 3550 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3551 } 3552 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3553 PetscFunctionReturn(0); 3554 } 3555 3556 #undef __FUNCT__ 3557 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3558 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3559 { 3560 PetscSection coordSection, newCoordSection; 3561 Vec coordinates; 3562 PetscInt *depthEnd; 3563 PetscInt dim, depth = 0, d, vStart, vEnd, v; 3564 PetscErrorCode ierr; 3565 3566 PetscFunctionBegin; 3567 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3568 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3569 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3570 for(d = 0; d <= depth; ++d) { 3571 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3572 } 3573 /* Step 8: Convert coordinates */ 3574 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3575 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3576 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3577 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3578 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3579 ierr = PetscSectionSetChart(newCoordSection, DMPlexShiftPoint_Private(vStart, depth, depthEnd, depthShift), DMPlexShiftPoint_Private(vEnd, depth, depthEnd, depthShift));CHKERRQ(ierr); 3580 for(v = vStart; v < vEnd; ++v) { 3581 const PetscInt newv = DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift); 3582 ierr = PetscSectionSetDof(newCoordSection, newv, dim);CHKERRQ(ierr); 3583 ierr = PetscSectionSetFieldDof(newCoordSection, newv, 0, dim);CHKERRQ(ierr); 3584 } 3585 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3586 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3587 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3588 ierr = DMSetCoordinatesLocal(dmNew, coordinates);CHKERRQ(ierr); 3589 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3590 PetscFunctionReturn(0); 3591 } 3592 3593 #undef __FUNCT__ 3594 #define __FUNCT__ "DMPlexShiftSF_Private" 3595 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3596 { 3597 PetscInt *depthEnd; 3598 PetscInt depth = 0, d; 3599 PetscSF sfPoint, sfPointNew; 3600 const PetscSFNode *remotePoints; 3601 PetscSFNode *gremotePoints; 3602 const PetscInt *localPoints; 3603 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3604 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3605 PetscMPIInt numProcs; 3606 PetscErrorCode ierr; 3607 3608 PetscFunctionBegin; 3609 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3610 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3611 for(d = 0; d <= depth; ++d) { 3612 totShift += depthShift[d]; 3613 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3614 } 3615 /* Step 9: Convert pointSF */ 3616 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3617 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3618 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3619 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3620 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3621 if (numRoots >= 0) { 3622 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3623 for(l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3624 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3625 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3626 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3627 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3628 for(l = 0; l < numLeaves; ++l) { 3629 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3630 gremotePoints[l].rank = remotePoints[l].rank; 3631 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3632 } 3633 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3634 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3635 } 3636 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3637 PetscFunctionReturn(0); 3638 } 3639 3640 #undef __FUNCT__ 3641 #define __FUNCT__ "DMPlexShiftLabels_Private" 3642 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3643 { 3644 PetscSF sfPoint; 3645 DMLabel vtkLabel, ghostLabel; 3646 PetscInt *depthEnd; 3647 const PetscSFNode *leafRemote; 3648 const PetscInt *leafLocal; 3649 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3650 PetscMPIInt rank; 3651 PetscErrorCode ierr; 3652 3653 PetscFunctionBegin; 3654 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3655 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3656 for(d = 0; d <= depth; ++d) { 3657 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3658 } 3659 /* Step 10: Convert labels */ 3660 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3661 for(l = 0; l < numLabels; ++l) { 3662 DMLabel label, newlabel; 3663 const char *lname; 3664 PetscBool isDepth; 3665 IS valueIS; 3666 const PetscInt *values; 3667 PetscInt numValues, val; 3668 3669 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3670 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3671 if (isDepth) continue; 3672 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3673 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3674 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3675 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3676 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3677 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3678 for(val = 0; val < numValues; ++val) { 3679 IS pointIS; 3680 const PetscInt *points; 3681 PetscInt numPoints, p; 3682 3683 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3684 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3685 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3686 for(p = 0; p < numPoints; ++p) { 3687 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3688 3689 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3690 } 3691 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3692 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3693 } 3694 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3695 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3696 } 3697 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3698 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3699 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3700 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3701 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3702 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3703 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3704 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3705 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3706 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3707 for(l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3708 for(; c < leafLocal[l] && c < cEnd; ++c) { 3709 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3710 } 3711 if (leafLocal[l] >= cEnd) break; 3712 if (leafRemote[l].rank == rank) { 3713 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3714 } else { 3715 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3716 } 3717 } 3718 for(; c < cEnd; ++c) { 3719 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3720 } 3721 if (0) { 3722 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3723 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3724 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3725 } 3726 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3727 for(f = fStart; f < fEnd; ++f) { 3728 PetscInt numCells; 3729 3730 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3731 if (numCells < 2) { 3732 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3733 } else { 3734 const PetscInt *cells = PETSC_NULL; 3735 PetscInt vA, vB; 3736 3737 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3738 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3739 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3740 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3741 } 3742 } 3743 if (0) { 3744 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3745 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3746 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3747 } 3748 PetscFunctionReturn(0); 3749 } 3750 3751 #undef __FUNCT__ 3752 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3753 /*@C 3754 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3755 3756 Collective on dm 3757 3758 Input Parameters: 3759 + dm - The original DM 3760 - labelName - The label specifying the boundary faces (this could be auto-generated) 3761 3762 Output Parameters: 3763 + numGhostCells - The number of ghost cells added to the DM 3764 - dmGhosted - The new DM 3765 3766 Level: developer 3767 3768 .seealso: DMCreate() 3769 */ 3770 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3771 { 3772 DMLabel label; 3773 IS valueIS; 3774 const PetscInt *values; 3775 PetscInt *depthShift; 3776 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3777 PetscErrorCode ierr; 3778 3779 PetscFunctionBegin; 3780 /* Count ghost cells */ 3781 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3782 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3783 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3784 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3785 *numGhostCells = 0; 3786 for(fs = 0; fs < numFS; ++fs) { 3787 PetscInt numBdFaces; 3788 3789 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3790 *numGhostCells += numBdFaces; 3791 } 3792 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3793 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3794 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3795 if (depth >= 0) {depthShift[depth] = *numGhostCells;} 3796 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3797 /* Step 3: Set cone/support sizes for new points */ 3798 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3799 for(c = cEnd; c < cEnd + *numGhostCells; ++c) { 3800 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3801 } 3802 for(fs = 0; fs < numFS; ++fs) { 3803 IS faceIS; 3804 const PetscInt *faces; 3805 PetscInt numFaces, f; 3806 3807 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3808 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3809 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3810 for(f = 0; f < numFaces; ++f) { 3811 PetscInt size; 3812 3813 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3814 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3815 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3816 } 3817 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3818 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3819 } 3820 /* Step 4: Setup ghosted DM */ 3821 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3822 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3823 /* Step 6: Set cones and supports for new points */ 3824 ghostCell = cEnd; 3825 for(fs = 0; fs < numFS; ++fs) { 3826 IS faceIS; 3827 const PetscInt *faces; 3828 PetscInt numFaces, f; 3829 3830 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3831 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3832 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3833 for(f = 0; f < numFaces; ++f, ++ghostCell) { 3834 PetscInt newFace = faces[f] + *numGhostCells; 3835 3836 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3837 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3838 } 3839 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3840 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3841 } 3842 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3843 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3844 /* Step 7: Stratify */ 3845 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3846 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3847 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3848 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3849 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3850 PetscFunctionReturn(0); 3851 } 3852 3853 #undef __FUNCT__ 3854 #define __FUNCT__ "DMPlexConstructGhostCells" 3855 /*@C 3856 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3857 3858 Collective on dm 3859 3860 Input Parameters: 3861 + dm - The original DM 3862 - labelName - The label specifying the boundary faces (this could be auto-generated) 3863 3864 Output Parameters: 3865 + numGhostCells - The number of ghost cells added to the DM 3866 - dmGhosted - The new DM 3867 3868 Level: developer 3869 3870 .seealso: DMCreate() 3871 */ 3872 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3873 { 3874 DM gdm; 3875 PetscInt dim; 3876 PetscErrorCode ierr; 3877 3878 PetscFunctionBegin; 3879 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3880 PetscValidPointer(numGhostCells, 3); 3881 PetscValidPointer(dmGhosted, 4); 3882 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3883 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3884 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3885 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3886 switch(dim) { 3887 case 2: 3888 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3889 break; 3890 default: 3891 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3892 } 3893 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3894 *dmGhosted = gdm; 3895 PetscFunctionReturn(0); 3896 } 3897 3898 #undef __FUNCT__ 3899 #define __FUNCT__ "DMPlexInterpolate_2D" 3900 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 3901 { 3902 DM idm; 3903 DM_Plex *mesh; 3904 PetscHashIJ edgeTable; 3905 PetscInt *off; 3906 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 3907 PetscInt numEdges, firstEdge, edge, e; 3908 PetscErrorCode ierr; 3909 3910 PetscFunctionBegin; 3911 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3912 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3913 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3914 numCells = cEnd - cStart; 3915 numVertices = vEnd - vStart; 3916 firstEdge = numCells + numVertices; 3917 numEdges = 0 ; 3918 /* Count edges using algorithm from CreateNeighborCSR */ 3919 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 3920 if (off) { 3921 PetscInt numCorners = 0; 3922 3923 numEdges = off[numCells]/2; 3924 #if 0 3925 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 3926 numEdges += 3*numCells - off[numCells]; 3927 #else 3928 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 3929 for(c = cStart; c < cEnd; ++c) { 3930 PetscInt coneSize; 3931 3932 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 3933 numCorners += coneSize; 3934 } 3935 numEdges += numCorners - off[numCells]; 3936 #endif 3937 } 3938 #if 0 3939 /* Check Euler characteristic V - E + F = 1 */ 3940 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 3941 #endif 3942 /* Create interpolated mesh */ 3943 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 3944 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 3945 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 3946 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 3947 for (c = 0; c < numCells; ++c) { 3948 PetscInt numCorners; 3949 3950 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 3951 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 3952 } 3953 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 3954 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 3955 } 3956 ierr = DMSetUp(idm);CHKERRQ(ierr); 3957 /* Get edge cones from subsets of cell vertices */ 3958 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 3959 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 3960 3961 for (c = 0, edge = firstEdge; c < numCells; ++c) { 3962 const PetscInt *cellFaces; 3963 PetscInt numCellFaces, faceSize, cf; 3964 3965 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 3966 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 3967 for (cf = 0; cf < numCellFaces; ++cf) { 3968 #if 1 3969 PetscHashIJKey key = {PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]), 3970 PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1])}; 3971 3972 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 3973 if (e < 0) { 3974 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3975 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 3976 e = edge++; 3977 } 3978 #else 3979 PetscBool found = PETSC_FALSE; 3980 3981 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 3982 for (e = firstEdge; e < edge; ++e) { 3983 const PetscInt *cone; 3984 3985 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 3986 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 3987 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 3988 found = PETSC_TRUE; 3989 break; 3990 } 3991 } 3992 if (!found) { 3993 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3994 ++edge; 3995 } 3996 #endif 3997 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 3998 } 3999 } 4000 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4001 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4002 ierr = PetscFree(off);CHKERRQ(ierr); 4003 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4004 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4005 mesh = (DM_Plex *) (idm)->data; 4006 /* Orient edges */ 4007 for (c = 0; c < numCells; ++c) { 4008 const PetscInt *cone = PETSC_NULL, *cellFaces; 4009 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4010 4011 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4012 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4013 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4014 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4015 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4016 for (cf = 0; cf < numCellFaces; ++cf) { 4017 const PetscInt *econe = PETSC_NULL; 4018 PetscInt esize; 4019 4020 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4021 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4022 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]); 4023 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4024 /* Correctly oriented */ 4025 mesh->coneOrientations[coff+cf] = 0; 4026 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4027 /* Start at index 1, and reverse orientation */ 4028 mesh->coneOrientations[coff+cf] = -(1+1); 4029 } 4030 } 4031 } 4032 *dmInt = idm; 4033 PetscFunctionReturn(0); 4034 } 4035 4036 #undef __FUNCT__ 4037 #define __FUNCT__ "DMPlexInterpolate_3D" 4038 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4039 { 4040 DM idm, fdm; 4041 DM_Plex *mesh; 4042 PetscInt *off; 4043 const PetscInt numCorners = 4; 4044 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4045 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4046 PetscErrorCode ierr; 4047 4048 PetscFunctionBegin; 4049 { 4050 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4051 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4052 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4053 } 4054 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4055 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4056 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4057 numCells = cEnd - cStart; 4058 numVertices = vEnd - vStart; 4059 firstFace = numCells + numVertices; 4060 numFaces = 0 ; 4061 /* Count faces using algorithm from CreateNeighborCSR */ 4062 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4063 if (off) { 4064 numFaces = off[numCells]/2; 4065 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4066 numFaces += 4*numCells - off[numCells]; 4067 } 4068 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4069 firstEdge = firstFace + numFaces; 4070 numEdges = numVertices + numFaces - numCells - 1; 4071 /* Create interpolated mesh */ 4072 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4073 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4074 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4075 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4076 for (c = 0; c < numCells; ++c) { 4077 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4078 } 4079 for (f = firstFace; f < firstFace+numFaces; ++f) { 4080 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4081 } 4082 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4083 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4084 } 4085 ierr = DMSetUp(idm);CHKERRQ(ierr); 4086 /* Get face cones from subsets of cell vertices */ 4087 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4088 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4089 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4090 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4091 for (f = firstFace; f < firstFace+numFaces; ++f) { 4092 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4093 } 4094 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4095 for (c = 0, face = firstFace; c < numCells; ++c) { 4096 const PetscInt *cellFaces; 4097 PetscInt numCellFaces, faceSize, cf; 4098 4099 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4100 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4101 for (cf = 0; cf < numCellFaces; ++cf) { 4102 PetscBool found = PETSC_FALSE; 4103 4104 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4105 for (f = firstFace; f < face; ++f) { 4106 const PetscInt *cone = PETSC_NULL; 4107 4108 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4109 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4110 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4111 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4112 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4113 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4114 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4115 found = PETSC_TRUE; 4116 break; 4117 } 4118 } 4119 if (!found) { 4120 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4121 /* Save the vertices for orientation calculation */ 4122 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4123 ++face; 4124 } 4125 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4126 } 4127 } 4128 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4129 /* Get edge cones from subsets of face vertices */ 4130 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4131 const PetscInt *cellFaces; 4132 PetscInt numCellFaces, faceSize, cf; 4133 4134 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4135 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4136 for (cf = 0; cf < numCellFaces; ++cf) { 4137 PetscBool found = PETSC_FALSE; 4138 4139 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4140 for (e = firstEdge; e < edge; ++e) { 4141 const PetscInt *cone = PETSC_NULL; 4142 4143 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4144 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4145 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4146 found = PETSC_TRUE; 4147 break; 4148 } 4149 } 4150 if (!found) { 4151 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4152 ++edge; 4153 } 4154 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4155 } 4156 } 4157 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4158 ierr = PetscFree(off);CHKERRQ(ierr); 4159 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4160 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4161 mesh = (DM_Plex *) (idm)->data; 4162 /* Orient edges */ 4163 for (f = firstFace; f < firstFace+numFaces; ++f) { 4164 const PetscInt *cone, *cellFaces; 4165 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4166 4167 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4168 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4169 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4170 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4171 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4172 for (cf = 0; cf < numCellFaces; ++cf) { 4173 const PetscInt *econe; 4174 PetscInt esize; 4175 4176 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4177 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4178 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]); 4179 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4180 /* Correctly oriented */ 4181 mesh->coneOrientations[coff+cf] = 0; 4182 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4183 /* Start at index 1, and reverse orientation */ 4184 mesh->coneOrientations[coff+cf] = -(1+1); 4185 } 4186 } 4187 } 4188 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4189 /* Orient faces */ 4190 for (c = 0; c < numCells; ++c) { 4191 const PetscInt *cone, *cellFaces; 4192 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4193 4194 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4195 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4196 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4197 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4198 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4199 for (cf = 0; cf < numCellFaces; ++cf) { 4200 PetscInt *origClosure = PETSC_NULL, *closure; 4201 PetscInt closureSize, i; 4202 4203 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4204 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4205 for (i = 4; i < 7; ++i) { 4206 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); 4207 } 4208 closure = &origClosure[4*2]; 4209 /* Remember that this is the orientation for edges, not vertices */ 4210 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4211 /* Correctly oriented */ 4212 mesh->coneOrientations[coff+cf] = 0; 4213 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4214 /* Shifted by 1 */ 4215 mesh->coneOrientations[coff+cf] = 1; 4216 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4217 /* Shifted by 2 */ 4218 mesh->coneOrientations[coff+cf] = 2; 4219 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4220 /* Start at edge 1, and reverse orientation */ 4221 mesh->coneOrientations[coff+cf] = -(1+1); 4222 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4223 /* Start at index 0, and reverse orientation */ 4224 mesh->coneOrientations[coff+cf] = -(0+1); 4225 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4226 /* Start at index 2, and reverse orientation */ 4227 mesh->coneOrientations[coff+cf] = -(2+1); 4228 } 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); 4229 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4230 } 4231 } 4232 { 4233 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4234 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4235 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4236 } 4237 *dmInt = idm; 4238 PetscFunctionReturn(0); 4239 } 4240 4241 #undef __FUNCT__ 4242 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4243 /* 4244 This takes as input the common mesh generator output, a list of the vertices for each cell 4245 */ 4246 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4247 { 4248 PetscInt *cone, c, p; 4249 PetscErrorCode ierr; 4250 4251 PetscFunctionBegin; 4252 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4253 for (c = 0; c < numCells; ++c) { 4254 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4255 } 4256 ierr = DMSetUp(dm);CHKERRQ(ierr); 4257 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4258 for (c = 0; c < numCells; ++c) { 4259 for (p = 0; p < numCorners; ++p) { 4260 cone[p] = cells[c*numCorners+p]+numCells; 4261 } 4262 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4263 } 4264 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4265 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4266 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4267 PetscFunctionReturn(0); 4268 } 4269 4270 #undef __FUNCT__ 4271 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4272 /* 4273 This takes as input the coordinates for each vertex 4274 */ 4275 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4276 { 4277 PetscSection coordSection; 4278 Vec coordinates; 4279 PetscScalar *coords; 4280 PetscInt coordSize, v, d; 4281 PetscErrorCode ierr; 4282 4283 PetscFunctionBegin; 4284 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4285 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4286 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4287 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4288 for (v = numCells; v < numCells+numVertices; ++v) { 4289 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4290 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4291 } 4292 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4293 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4294 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4295 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4296 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4297 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4298 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4299 for (v = 0; v < numVertices; ++v) { 4300 for (d = 0; d < spaceDim; ++d) { 4301 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4302 } 4303 } 4304 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4305 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4306 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4307 PetscFunctionReturn(0); 4308 } 4309 4310 #undef __FUNCT__ 4311 #define __FUNCT__ "DMPlexCreateFromCellList" 4312 /* 4313 This takes as input the common mesh generator output, a list of the vertices for each cell 4314 */ 4315 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4316 { 4317 PetscErrorCode ierr; 4318 4319 PetscFunctionBegin; 4320 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4321 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4322 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4323 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4324 if (interpolate) { 4325 DM idm; 4326 4327 switch(dim) { 4328 case 2: 4329 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4330 case 3: 4331 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4332 default: 4333 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4334 } 4335 ierr = DMDestroy(dm);CHKERRQ(ierr); 4336 *dm = idm; 4337 } 4338 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4339 PetscFunctionReturn(0); 4340 } 4341 4342 #ifdef PETSC_HAVE_TRIANGLE 4343 #include <triangle.h> 4344 4345 #undef __FUNCT__ 4346 #define __FUNCT__ "InitInput_Triangle" 4347 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) { 4348 PetscFunctionBegin; 4349 inputCtx->numberofpoints = 0; 4350 inputCtx->numberofpointattributes = 0; 4351 inputCtx->pointlist = PETSC_NULL; 4352 inputCtx->pointattributelist = PETSC_NULL; 4353 inputCtx->pointmarkerlist = PETSC_NULL; 4354 inputCtx->numberofsegments = 0; 4355 inputCtx->segmentlist = PETSC_NULL; 4356 inputCtx->segmentmarkerlist = PETSC_NULL; 4357 inputCtx->numberoftriangleattributes = 0; 4358 inputCtx->trianglelist = PETSC_NULL; 4359 inputCtx->numberofholes = 0; 4360 inputCtx->holelist = PETSC_NULL; 4361 inputCtx->numberofregions = 0; 4362 inputCtx->regionlist = PETSC_NULL; 4363 PetscFunctionReturn(0); 4364 } 4365 4366 #undef __FUNCT__ 4367 #define __FUNCT__ "InitOutput_Triangle" 4368 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) { 4369 PetscFunctionBegin; 4370 outputCtx->numberofpoints = 0; 4371 outputCtx->pointlist = PETSC_NULL; 4372 outputCtx->pointattributelist = PETSC_NULL; 4373 outputCtx->pointmarkerlist = PETSC_NULL; 4374 outputCtx->numberoftriangles = 0; 4375 outputCtx->trianglelist = PETSC_NULL; 4376 outputCtx->triangleattributelist = PETSC_NULL; 4377 outputCtx->neighborlist = PETSC_NULL; 4378 outputCtx->segmentlist = PETSC_NULL; 4379 outputCtx->segmentmarkerlist = PETSC_NULL; 4380 outputCtx->numberofedges = 0; 4381 outputCtx->edgelist = PETSC_NULL; 4382 outputCtx->edgemarkerlist = PETSC_NULL; 4383 PetscFunctionReturn(0); 4384 } 4385 4386 #undef __FUNCT__ 4387 #define __FUNCT__ "FiniOutput_Triangle" 4388 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) { 4389 PetscFunctionBegin; 4390 free(outputCtx->pointmarkerlist); 4391 free(outputCtx->edgelist); 4392 free(outputCtx->edgemarkerlist); 4393 free(outputCtx->trianglelist); 4394 free(outputCtx->neighborlist); 4395 PetscFunctionReturn(0); 4396 } 4397 4398 #undef __FUNCT__ 4399 #define __FUNCT__ "DMPlexGenerate_Triangle" 4400 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4401 { 4402 MPI_Comm comm = ((PetscObject) boundary)->comm; 4403 PetscInt dim = 2; 4404 const PetscBool createConvexHull = PETSC_FALSE; 4405 const PetscBool constrained = PETSC_FALSE; 4406 struct triangulateio in; 4407 struct triangulateio out; 4408 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4409 PetscMPIInt rank; 4410 PetscErrorCode ierr; 4411 4412 PetscFunctionBegin; 4413 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4414 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4415 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4416 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4417 in.numberofpoints = vEnd - vStart; 4418 if (in.numberofpoints > 0) { 4419 PetscSection coordSection; 4420 Vec coordinates; 4421 PetscScalar *array; 4422 4423 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4424 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4425 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4426 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4427 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4428 for (v = vStart; v < vEnd; ++v) { 4429 const PetscInt idx = v - vStart; 4430 PetscInt off, d; 4431 4432 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4433 for (d = 0; d < dim; ++d) { 4434 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4435 } 4436 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4437 } 4438 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4439 } 4440 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4441 in.numberofsegments = eEnd - eStart; 4442 if (in.numberofsegments > 0) { 4443 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4444 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4445 for (e = eStart; e < eEnd; ++e) { 4446 const PetscInt idx = e - eStart; 4447 const PetscInt *cone; 4448 4449 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4450 in.segmentlist[idx*2+0] = cone[0] - vStart; 4451 in.segmentlist[idx*2+1] = cone[1] - vStart; 4452 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4453 } 4454 } 4455 #if 0 /* Do not currently support holes */ 4456 PetscReal *holeCoords; 4457 PetscInt h, d; 4458 4459 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4460 if (in.numberofholes > 0) { 4461 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4462 for (h = 0; h < in.numberofholes; ++h) { 4463 for (d = 0; d < dim; ++d) { 4464 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4465 } 4466 } 4467 } 4468 #endif 4469 if (!rank) { 4470 char args[32]; 4471 4472 /* Take away 'Q' for verbose output */ 4473 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4474 if (createConvexHull) { 4475 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4476 } 4477 if (constrained) { 4478 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4479 } 4480 triangulate(args, &in, &out, PETSC_NULL); 4481 } 4482 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4483 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4484 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4485 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4486 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4487 4488 { 4489 const PetscInt numCorners = 3; 4490 const PetscInt numCells = out.numberoftriangles; 4491 const PetscInt numVertices = out.numberofpoints; 4492 const int *cells = out.trianglelist; 4493 const double *meshCoords = out.pointlist; 4494 4495 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4496 /* Set labels */ 4497 for (v = 0; v < numVertices; ++v) { 4498 if (out.pointmarkerlist[v]) { 4499 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4500 } 4501 } 4502 if (interpolate) { 4503 for (e = 0; e < out.numberofedges; e++) { 4504 if (out.edgemarkerlist[e]) { 4505 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4506 const PetscInt *edges; 4507 PetscInt numEdges; 4508 4509 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4510 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4511 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4512 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4513 } 4514 } 4515 } 4516 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4517 } 4518 #if 0 /* Do not currently support holes */ 4519 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4520 #endif 4521 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4522 PetscFunctionReturn(0); 4523 } 4524 4525 #undef __FUNCT__ 4526 #define __FUNCT__ "DMPlexRefine_Triangle" 4527 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4528 { 4529 MPI_Comm comm = ((PetscObject) dm)->comm; 4530 PetscInt dim = 2; 4531 struct triangulateio in; 4532 struct triangulateio out; 4533 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4534 PetscMPIInt rank; 4535 PetscErrorCode ierr; 4536 4537 PetscFunctionBegin; 4538 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4539 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4540 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4541 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4542 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4543 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4544 in.numberofpoints = vEnd - vStart; 4545 if (in.numberofpoints > 0) { 4546 PetscSection coordSection; 4547 Vec coordinates; 4548 PetscScalar *array; 4549 4550 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4551 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4552 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4553 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4554 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4555 for (v = vStart; v < vEnd; ++v) { 4556 const PetscInt idx = v - vStart; 4557 PetscInt off, d; 4558 4559 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4560 for (d = 0; d < dim; ++d) { 4561 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4562 } 4563 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4564 } 4565 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4566 } 4567 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4568 in.numberofcorners = 3; 4569 in.numberoftriangles = cEnd - cStart; 4570 in.trianglearealist = (double *) maxVolumes; 4571 if (in.numberoftriangles > 0) { 4572 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4573 for (c = cStart; c < cEnd; ++c) { 4574 const PetscInt idx = c - cStart; 4575 PetscInt *closure = PETSC_NULL; 4576 PetscInt closureSize; 4577 4578 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4579 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4580 for (v = 0; v < 3; ++v) { 4581 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4582 } 4583 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4584 } 4585 } 4586 /* TODO: Segment markers are missing on input */ 4587 #if 0 /* Do not currently support holes */ 4588 PetscReal *holeCoords; 4589 PetscInt h, d; 4590 4591 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4592 if (in.numberofholes > 0) { 4593 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4594 for (h = 0; h < in.numberofholes; ++h) { 4595 for (d = 0; d < dim; ++d) { 4596 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4597 } 4598 } 4599 } 4600 #endif 4601 if (!rank) { 4602 char args[32]; 4603 4604 /* Take away 'Q' for verbose output */ 4605 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4606 triangulate(args, &in, &out, PETSC_NULL); 4607 } 4608 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4609 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4610 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4611 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4612 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4613 4614 { 4615 const PetscInt numCorners = 3; 4616 const PetscInt numCells = out.numberoftriangles; 4617 const PetscInt numVertices = out.numberofpoints; 4618 const int *cells = out.trianglelist; 4619 const double *meshCoords = out.pointlist; 4620 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4621 4622 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4623 /* Set labels */ 4624 for (v = 0; v < numVertices; ++v) { 4625 if (out.pointmarkerlist[v]) { 4626 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4627 } 4628 } 4629 if (interpolate) { 4630 PetscInt e; 4631 4632 for (e = 0; e < out.numberofedges; e++) { 4633 if (out.edgemarkerlist[e]) { 4634 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4635 const PetscInt *edges; 4636 PetscInt numEdges; 4637 4638 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4639 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4640 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4641 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4642 } 4643 } 4644 } 4645 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4646 } 4647 #if 0 /* Do not currently support holes */ 4648 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4649 #endif 4650 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4651 PetscFunctionReturn(0); 4652 } 4653 #endif 4654 4655 #ifdef PETSC_HAVE_TETGEN 4656 #include <tetgen.h> 4657 #undef __FUNCT__ 4658 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4659 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4660 { 4661 MPI_Comm comm = ((PetscObject) boundary)->comm; 4662 const PetscInt dim = 3; 4663 ::tetgenio in; 4664 ::tetgenio out; 4665 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4666 PetscMPIInt rank; 4667 PetscErrorCode ierr; 4668 4669 PetscFunctionBegin; 4670 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4671 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4672 in.numberofpoints = vEnd - vStart; 4673 if (in.numberofpoints > 0) { 4674 PetscSection coordSection; 4675 Vec coordinates; 4676 PetscScalar *array; 4677 4678 in.pointlist = new double[in.numberofpoints*dim]; 4679 in.pointmarkerlist = new int[in.numberofpoints]; 4680 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4681 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4682 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4683 for (v = vStart; v < vEnd; ++v) { 4684 const PetscInt idx = v - vStart; 4685 PetscInt off, d; 4686 4687 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4688 for (d = 0; d < dim; ++d) { 4689 in.pointlist[idx*dim + d] = array[off+d]; 4690 } 4691 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4692 } 4693 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4694 } 4695 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4696 in.numberoffacets = fEnd - fStart; 4697 if (in.numberoffacets > 0) { 4698 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4699 in.facetmarkerlist = new int[in.numberoffacets]; 4700 for (f = fStart; f < fEnd; ++f) { 4701 const PetscInt idx = f - fStart; 4702 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 4703 4704 in.facetlist[idx].numberofpolygons = 1; 4705 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4706 in.facetlist[idx].numberofholes = 0; 4707 in.facetlist[idx].holelist = NULL; 4708 4709 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4710 for (p = 0; p < numPoints*2; p += 2) { 4711 const PetscInt point = points[p]; 4712 if ((point >= vStart) && (point < vEnd)) { 4713 points[numVertices++] = point; 4714 } 4715 } 4716 4717 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4718 poly->numberofvertices = numVertices; 4719 poly->vertexlist = new int[poly->numberofvertices]; 4720 for (v = 0; v < numVertices; ++v) { 4721 const PetscInt vIdx = points[v] - vStart; 4722 poly->vertexlist[v] = vIdx; 4723 } 4724 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4725 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4726 } 4727 } 4728 if (!rank) { 4729 char args[32]; 4730 4731 /* Take away 'Q' for verbose output */ 4732 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4733 ::tetrahedralize(args, &in, &out); 4734 } 4735 { 4736 const PetscInt numCorners = 4; 4737 const PetscInt numCells = out.numberoftetrahedra; 4738 const PetscInt numVertices = out.numberofpoints; 4739 const int *cells = out.tetrahedronlist; 4740 const double *meshCoords = out.pointlist; 4741 4742 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4743 /* Set labels */ 4744 for (v = 0; v < numVertices; ++v) { 4745 if (out.pointmarkerlist[v]) { 4746 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4747 } 4748 } 4749 if (interpolate) { 4750 PetscInt e; 4751 4752 for (e = 0; e < out.numberofedges; e++) { 4753 if (out.edgemarkerlist[e]) { 4754 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4755 const PetscInt *edges; 4756 PetscInt numEdges; 4757 4758 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4759 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4760 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4761 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4762 } 4763 } 4764 for (f = 0; f < out.numberoftrifaces; f++) { 4765 if (out.trifacemarkerlist[f]) { 4766 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4767 const PetscInt *faces; 4768 PetscInt numFaces; 4769 4770 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4771 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4772 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4773 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4774 } 4775 } 4776 } 4777 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4778 } 4779 PetscFunctionReturn(0); 4780 } 4781 4782 #undef __FUNCT__ 4783 #define __FUNCT__ "DMPlexRefine_Tetgen" 4784 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4785 { 4786 MPI_Comm comm = ((PetscObject) dm)->comm; 4787 const PetscInt dim = 3; 4788 ::tetgenio in; 4789 ::tetgenio out; 4790 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4791 PetscMPIInt rank; 4792 PetscErrorCode ierr; 4793 4794 PetscFunctionBegin; 4795 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4796 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4797 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4798 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4799 in.numberofpoints = vEnd - vStart; 4800 if (in.numberofpoints > 0) { 4801 PetscSection coordSection; 4802 Vec coordinates; 4803 PetscScalar *array; 4804 4805 in.pointlist = new double[in.numberofpoints*dim]; 4806 in.pointmarkerlist = new int[in.numberofpoints]; 4807 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4808 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4809 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4810 for (v = vStart; v < vEnd; ++v) { 4811 const PetscInt idx = v - vStart; 4812 PetscInt off, d; 4813 4814 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4815 for (d = 0; d < dim; ++d) { 4816 in.pointlist[idx*dim + d] = array[off+d]; 4817 } 4818 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4819 } 4820 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4821 } 4822 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4823 in.numberofcorners = 4; 4824 in.numberoftetrahedra = cEnd - cStart; 4825 in.tetrahedronvolumelist = (double *) maxVolumes; 4826 if (in.numberoftetrahedra > 0) { 4827 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 4828 for (c = cStart; c < cEnd; ++c) { 4829 const PetscInt idx = c - cStart; 4830 PetscInt *closure = PETSC_NULL; 4831 PetscInt closureSize; 4832 4833 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4834 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 4835 for (v = 0; v < 4; ++v) { 4836 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 4837 } 4838 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4839 } 4840 } 4841 // TODO: Put in boundary faces with markers 4842 if (!rank) { 4843 char args[32]; 4844 4845 /* Take away 'Q' for verbose output */ 4846 //ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); 4847 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 4848 ::tetrahedralize(args, &in, &out); 4849 } 4850 in.tetrahedronvolumelist = NULL; 4851 4852 { 4853 const PetscInt numCorners = 4; 4854 const PetscInt numCells = out.numberoftetrahedra; 4855 const PetscInt numVertices = out.numberofpoints; 4856 const int *cells = out.tetrahedronlist; 4857 const double *meshCoords = out.pointlist; 4858 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4859 4860 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4861 /* Set labels */ 4862 for (v = 0; v < numVertices; ++v) { 4863 if (out.pointmarkerlist[v]) { 4864 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4865 } 4866 } 4867 if (interpolate) { 4868 PetscInt e, f; 4869 4870 for (e = 0; e < out.numberofedges; e++) { 4871 if (out.edgemarkerlist[e]) { 4872 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4873 const PetscInt *edges; 4874 PetscInt numEdges; 4875 4876 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4877 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4878 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4879 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4880 } 4881 } 4882 for (f = 0; f < out.numberoftrifaces; f++) { 4883 if (out.trifacemarkerlist[f]) { 4884 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4885 const PetscInt *faces; 4886 PetscInt numFaces; 4887 4888 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4889 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4890 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4891 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4892 } 4893 } 4894 } 4895 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4896 } 4897 PetscFunctionReturn(0); 4898 } 4899 #endif 4900 4901 #ifdef PETSC_HAVE_CTETGEN 4902 #include "ctetgen.h" 4903 4904 #undef __FUNCT__ 4905 #define __FUNCT__ "DMPlexGenerate_CTetgen" 4906 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 4907 { 4908 MPI_Comm comm = ((PetscObject) boundary)->comm; 4909 const PetscInt dim = 3; 4910 PLC *in, *out; 4911 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 4912 PetscMPIInt rank; 4913 PetscErrorCode ierr; 4914 4915 PetscFunctionBegin; 4916 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 4917 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4918 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4919 ierr = PLCCreate(&in);CHKERRQ(ierr); 4920 ierr = PLCCreate(&out);CHKERRQ(ierr); 4921 in->numberofpoints = vEnd - vStart; 4922 if (in->numberofpoints > 0) { 4923 PetscSection coordSection; 4924 Vec coordinates; 4925 PetscScalar *array; 4926 4927 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 4928 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 4929 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4930 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4931 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4932 for (v = vStart; v < vEnd; ++v) { 4933 const PetscInt idx = v - vStart; 4934 PetscInt off, d, m; 4935 4936 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4937 for (d = 0; d < dim; ++d) { 4938 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4939 } 4940 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 4941 in->pointmarkerlist[idx] = (int) m; 4942 } 4943 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4944 } 4945 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4946 in->numberoffacets = fEnd - fStart; 4947 if (in->numberoffacets > 0) { 4948 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 4949 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 4950 for (f = fStart; f < fEnd; ++f) { 4951 const PetscInt idx = f - fStart; 4952 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 4953 polygon *poly; 4954 4955 in->facetlist[idx].numberofpolygons = 1; 4956 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 4957 in->facetlist[idx].numberofholes = 0; 4958 in->facetlist[idx].holelist = PETSC_NULL; 4959 4960 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4961 for (p = 0; p < numPoints*2; p += 2) { 4962 const PetscInt point = points[p]; 4963 if ((point >= vStart) && (point < vEnd)) { 4964 points[numVertices++] = point; 4965 } 4966 } 4967 4968 poly = in->facetlist[idx].polygonlist; 4969 poly->numberofvertices = numVertices; 4970 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 4971 for (v = 0; v < numVertices; ++v) { 4972 const PetscInt vIdx = points[v] - vStart; 4973 poly->vertexlist[v] = vIdx; 4974 } 4975 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 4976 in->facetmarkerlist[idx] = (int) m; 4977 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4978 } 4979 } 4980 if (!rank) { 4981 TetGenOpts t; 4982 4983 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 4984 t.in = boundary; /* Should go away */ 4985 t.plc = 1; 4986 t.quality = 1; 4987 t.edgesout = 1; 4988 t.zeroindex = 1; 4989 t.quiet = 1; 4990 t.verbose = verbose; 4991 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 4992 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 4993 } 4994 { 4995 const PetscInt numCorners = 4; 4996 const PetscInt numCells = out->numberoftetrahedra; 4997 const PetscInt numVertices = out->numberofpoints; 4998 const int *cells = out->tetrahedronlist; 4999 const double *meshCoords = out->pointlist; 5000 5001 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5002 /* Set labels */ 5003 for (v = 0; v < numVertices; ++v) { 5004 if (out->pointmarkerlist[v]) { 5005 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5006 } 5007 } 5008 if (interpolate) { 5009 PetscInt e; 5010 5011 for (e = 0; e < out->numberofedges; e++) { 5012 if (out->edgemarkerlist[e]) { 5013 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5014 const PetscInt *edges; 5015 PetscInt numEdges; 5016 5017 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5018 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5019 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5020 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5021 } 5022 } 5023 for (f = 0; f < out->numberoftrifaces; f++) { 5024 if (out->trifacemarkerlist[f]) { 5025 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5026 const PetscInt *faces; 5027 PetscInt numFaces; 5028 5029 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5030 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5031 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5032 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5033 } 5034 } 5035 } 5036 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5037 } 5038 5039 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5040 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5041 PetscFunctionReturn(0); 5042 } 5043 5044 #undef __FUNCT__ 5045 #define __FUNCT__ "DMPlexRefine_CTetgen" 5046 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5047 { 5048 MPI_Comm comm = ((PetscObject) dm)->comm; 5049 const PetscInt dim = 3; 5050 PLC *in, *out; 5051 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5052 PetscMPIInt rank; 5053 PetscErrorCode ierr; 5054 5055 PetscFunctionBegin; 5056 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5057 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5058 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5059 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5060 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5061 ierr = PLCCreate(&in);CHKERRQ(ierr); 5062 ierr = PLCCreate(&out);CHKERRQ(ierr); 5063 in->numberofpoints = vEnd - vStart; 5064 if (in->numberofpoints > 0) { 5065 PetscSection coordSection; 5066 Vec coordinates; 5067 PetscScalar *array; 5068 5069 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5070 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5071 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5072 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5073 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5074 for (v = vStart; v < vEnd; ++v) { 5075 const PetscInt idx = v - vStart; 5076 PetscInt off, d, m; 5077 5078 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5079 for (d = 0; d < dim; ++d) { 5080 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5081 } 5082 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5083 in->pointmarkerlist[idx] = (int) m; 5084 } 5085 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5086 } 5087 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5088 in->numberofcorners = 4; 5089 in->numberoftetrahedra = cEnd - cStart; 5090 in->tetrahedronvolumelist = maxVolumes; 5091 if (in->numberoftetrahedra > 0) { 5092 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5093 for (c = cStart; c < cEnd; ++c) { 5094 const PetscInt idx = c - cStart; 5095 PetscInt *closure = PETSC_NULL; 5096 PetscInt closureSize; 5097 5098 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5099 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5100 for (v = 0; v < 4; ++v) { 5101 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5102 } 5103 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5104 } 5105 } 5106 if (!rank) { 5107 TetGenOpts t; 5108 5109 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5110 t.in = dm; /* Should go away */ 5111 t.refine = 1; 5112 t.varvolume = 1; 5113 t.quality = 1; 5114 t.edgesout = 1; 5115 t.zeroindex = 1; 5116 t.quiet = 1; 5117 t.verbose = verbose; /* Change this */ 5118 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5119 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5120 } 5121 { 5122 const PetscInt numCorners = 4; 5123 const PetscInt numCells = out->numberoftetrahedra; 5124 const PetscInt numVertices = out->numberofpoints; 5125 const int *cells = out->tetrahedronlist; 5126 const double *meshCoords = out->pointlist; 5127 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5128 5129 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5130 /* Set labels */ 5131 for (v = 0; v < numVertices; ++v) { 5132 if (out->pointmarkerlist[v]) { 5133 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5134 } 5135 } 5136 if (interpolate) { 5137 PetscInt e, f; 5138 5139 for (e = 0; e < out->numberofedges; e++) { 5140 if (out->edgemarkerlist[e]) { 5141 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5142 const PetscInt *edges; 5143 PetscInt numEdges; 5144 5145 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5146 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5147 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5148 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5149 } 5150 } 5151 for (f = 0; f < out->numberoftrifaces; f++) { 5152 if (out->trifacemarkerlist[f]) { 5153 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5154 const PetscInt *faces; 5155 PetscInt numFaces; 5156 5157 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5158 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5159 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5160 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5161 } 5162 } 5163 } 5164 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5165 } 5166 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5167 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5168 PetscFunctionReturn(0); 5169 } 5170 #endif 5171 5172 #undef __FUNCT__ 5173 #define __FUNCT__ "DMPlexGenerate" 5174 /*@C 5175 DMPlexGenerate - Generates a mesh. 5176 5177 Not Collective 5178 5179 Input Parameters: 5180 + boundary - The DMPlex boundary object 5181 . name - The mesh generation package name 5182 - interpolate - Flag to create intermediate mesh elements 5183 5184 Output Parameter: 5185 . mesh - The DMPlex object 5186 5187 Level: intermediate 5188 5189 .keywords: mesh, elements 5190 .seealso: DMPlexCreate(), DMRefine() 5191 @*/ 5192 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5193 { 5194 PetscInt dim; 5195 char genname[1024]; 5196 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5197 PetscErrorCode ierr; 5198 5199 PetscFunctionBegin; 5200 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5201 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5202 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5203 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5204 if (flg) {name = genname;} 5205 if (name) { 5206 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5207 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5208 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5209 } 5210 switch(dim) { 5211 case 1: 5212 if (!name || isTriangle) { 5213 #ifdef PETSC_HAVE_TRIANGLE 5214 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5215 #else 5216 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5217 #endif 5218 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5219 break; 5220 case 2: 5221 if (!name || isCTetgen) { 5222 #ifdef PETSC_HAVE_CTETGEN 5223 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5224 #else 5225 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5226 #endif 5227 } else if (isTetgen) { 5228 #ifdef PETSC_HAVE_TETGEN 5229 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5230 #else 5231 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5232 #endif 5233 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5234 break; 5235 default: 5236 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5237 } 5238 PetscFunctionReturn(0); 5239 } 5240 5241 typedef PetscInt CellRefiner; 5242 5243 #undef __FUNCT__ 5244 #define __FUNCT__ "GetDepthStart_Private" 5245 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5246 { 5247 PetscFunctionBegin; 5248 if (cStart) *cStart = 0; 5249 if (vStart) *vStart = depthSize[depth]; 5250 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5251 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5252 PetscFunctionReturn(0); 5253 } 5254 5255 #undef __FUNCT__ 5256 #define __FUNCT__ "GetDepthEnd_Private" 5257 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5258 { 5259 PetscFunctionBegin; 5260 if (cEnd) *cEnd = depthSize[depth]; 5261 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5262 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5263 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5264 PetscFunctionReturn(0); 5265 } 5266 5267 #undef __FUNCT__ 5268 #define __FUNCT__ "CellRefinerGetSizes" 5269 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5270 { 5271 PetscInt cStart, cEnd, vStart, vEnd, fStart, fEnd, eStart, eEnd; 5272 PetscErrorCode ierr; 5273 5274 PetscFunctionBegin; 5275 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5276 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5277 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5278 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5279 switch(refiner) { 5280 case 1: 5281 /* Simplicial 2D */ 5282 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5283 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5284 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5285 break; 5286 case 2: 5287 /* Hex 2D */ 5288 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5289 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5290 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5291 break; 5292 default: 5293 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5294 } 5295 PetscFunctionReturn(0); 5296 } 5297 5298 #undef __FUNCT__ 5299 #define __FUNCT__ "CellRefinerSetConeSizes" 5300 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5301 { 5302 PetscInt depth, cStart, cStartNew, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fStartNew, fEnd, f, eStart, eStartNew, eEnd, r; 5303 PetscErrorCode ierr; 5304 5305 PetscFunctionBegin; 5306 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5307 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5308 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5309 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5310 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5311 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5312 switch(refiner) { 5313 case 1: 5314 /* Simplicial 2D */ 5315 /* All cells have 3 faces */ 5316 for(c = cStart; c < cEnd; ++c) { 5317 for(r = 0; r < 4; ++r) { 5318 const PetscInt newp = (c - cStart)*4 + r; 5319 5320 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5321 } 5322 } 5323 /* Split faces have 2 vertices and the same cells as the parent */ 5324 for(f = fStart; f < fEnd; ++f) { 5325 for(r = 0; r < 2; ++r) { 5326 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5327 PetscInt size; 5328 5329 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5330 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5331 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5332 } 5333 } 5334 /* Interior faces have 2 vertices and 2 cells */ 5335 for(c = cStart; c < cEnd; ++c) { 5336 for(r = 0; r < 3; ++r) { 5337 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5338 5339 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5340 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5341 } 5342 } 5343 /* Old vertices have identical supports */ 5344 for(v = vStart; v < vEnd; ++v) { 5345 const PetscInt newp = vStartNew + (v - vStart); 5346 PetscInt size; 5347 5348 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5349 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5350 } 5351 /* Face vertices have 2 + cells*2 supports */ 5352 for(f = fStart; f < fEnd; ++f) { 5353 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5354 PetscInt size; 5355 5356 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5357 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5358 } 5359 break; 5360 case 2: 5361 /* Hex 2D */ 5362 /* All cells have 4 faces */ 5363 for(c = cStart; c < cEnd; ++c) { 5364 for(r = 0; r < 4; ++r) { 5365 const PetscInt newp = (c - cStart)*4 + r; 5366 5367 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5368 } 5369 } 5370 /* Split faces have 2 vertices and the same cells as the parent */ 5371 for(f = fStart; f < fEnd; ++f) { 5372 for(r = 0; r < 2; ++r) { 5373 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5374 PetscInt size; 5375 5376 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5377 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5378 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5379 } 5380 } 5381 /* Interior faces have 2 vertices and 2 cells */ 5382 for(c = cStart; c < cEnd; ++c) { 5383 for(r = 0; r < 4; ++r) { 5384 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5385 5386 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5387 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5388 } 5389 } 5390 /* Old vertices have identical supports */ 5391 for(v = vStart; v < vEnd; ++v) { 5392 const PetscInt newp = vStartNew + (v - vStart); 5393 PetscInt size; 5394 5395 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5396 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5397 } 5398 /* Face vertices have 2 + cells supports */ 5399 for(f = fStart; f < fEnd; ++f) { 5400 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5401 PetscInt size; 5402 5403 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5404 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5405 } 5406 /* Cell vertices have 4 supports */ 5407 for(c = cStart; c < cEnd; ++c) { 5408 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5409 5410 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5411 } 5412 break; 5413 default: 5414 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5415 } 5416 PetscFunctionReturn(0); 5417 } 5418 5419 #undef __FUNCT__ 5420 #define __FUNCT__ "CellRefinerSetCones" 5421 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5422 { 5423 PetscInt depth, cStart, cEnd, cStartNew, cEndNew, c, vStart, vEnd, vStartNew, vEndNew, v, fStart, fEnd, fStartNew, fEndNew, f, eStart, eEnd, eStartNew, eEndNew, r, p; 5424 PetscInt maxSupportSize, *supportRef; 5425 PetscErrorCode ierr; 5426 5427 PetscFunctionBegin; 5428 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5429 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5430 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5431 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5432 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5433 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5434 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5435 switch(refiner) { 5436 case 1: 5437 /* Simplicial 2D */ 5438 /* 5439 2 5440 |\ 5441 | \ 5442 | \ 5443 | \ 5444 | C \ 5445 | \ 5446 | \ 5447 2---1---1 5448 |\ D / \ 5449 | 2 0 \ 5450 |A \ / B \ 5451 0---0-------1 5452 */ 5453 /* All cells have 3 faces */ 5454 for(c = cStart; c < cEnd; ++c) { 5455 const PetscInt newp = (c - cStart)*4; 5456 const PetscInt *cone, *ornt; 5457 PetscInt coneNew[3], orntNew[3]; 5458 5459 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5460 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5461 /* A triangle */ 5462 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5463 orntNew[0] = ornt[0]; 5464 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5465 orntNew[1] = -2; 5466 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5467 orntNew[2] = ornt[2]; 5468 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5469 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5470 #if 1 5471 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); 5472 for(p = 0; p < 3; ++p) { 5473 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); 5474 } 5475 #endif 5476 /* B triangle */ 5477 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5478 orntNew[0] = ornt[0]; 5479 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5480 orntNew[1] = ornt[1]; 5481 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5482 orntNew[2] = -2; 5483 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5484 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5485 #if 1 5486 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); 5487 for(p = 0; p < 3; ++p) { 5488 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); 5489 } 5490 #endif 5491 /* C triangle */ 5492 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5493 orntNew[0] = -2; 5494 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5495 orntNew[1] = ornt[1]; 5496 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5497 orntNew[2] = ornt[2]; 5498 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5499 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5500 #if 1 5501 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); 5502 for(p = 0; p < 3; ++p) { 5503 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); 5504 } 5505 #endif 5506 /* D triangle */ 5507 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5508 orntNew[0] = 0; 5509 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5510 orntNew[1] = 0; 5511 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5512 orntNew[2] = 0; 5513 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5514 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5515 #if 1 5516 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); 5517 for(p = 0; p < 3; ++p) { 5518 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); 5519 } 5520 #endif 5521 } 5522 /* Split faces have 2 vertices and the same cells as the parent */ 5523 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5524 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5525 for(f = fStart; f < fEnd; ++f) { 5526 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5527 5528 for(r = 0; r < 2; ++r) { 5529 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5530 const PetscInt *cone, *support; 5531 PetscInt coneNew[2], coneSize, c, supportSize, s; 5532 5533 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5534 coneNew[0] = vStartNew + (cone[0] - vStart); 5535 coneNew[1] = vStartNew + (cone[1] - vStart); 5536 coneNew[(r+1)%2] = newv; 5537 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5538 #if 1 5539 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5540 for(p = 0; p < 2; ++p) { 5541 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); 5542 } 5543 #endif 5544 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5545 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5546 for(s = 0; s < supportSize; ++s) { 5547 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5548 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5549 for(c = 0; c < coneSize; ++c) { 5550 if (cone[c] == f) { 5551 break; 5552 } 5553 } 5554 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5555 } 5556 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5557 #if 1 5558 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5559 for(p = 0; p < supportSize; ++p) { 5560 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); 5561 } 5562 #endif 5563 } 5564 } 5565 /* Interior faces have 2 vertices and 2 cells */ 5566 for(c = cStart; c < cEnd; ++c) { 5567 const PetscInt *cone; 5568 5569 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5570 for(r = 0; r < 3; ++r) { 5571 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5572 PetscInt coneNew[2]; 5573 PetscInt supportNew[2]; 5574 5575 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5576 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5577 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5578 #if 1 5579 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5580 for(p = 0; p < 2; ++p) { 5581 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); 5582 } 5583 #endif 5584 supportNew[0] = (c - cStart)*4 + r; 5585 supportNew[1] = (c - cStart)*4 + 3; 5586 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5587 #if 1 5588 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5589 for(p = 0; p < 2; ++p) { 5590 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); 5591 } 5592 #endif 5593 } 5594 } 5595 /* Old vertices have identical supports */ 5596 for(v = vStart; v < vEnd; ++v) { 5597 const PetscInt newp = vStartNew + (v - vStart); 5598 const PetscInt *support, *cone; 5599 PetscInt size, s; 5600 5601 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5602 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5603 for(s = 0; s < size; ++s) { 5604 PetscInt r = 0; 5605 5606 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5607 if (cone[1] == v) r = 1; 5608 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5609 } 5610 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5611 #if 1 5612 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5613 for(p = 0; p < size; ++p) { 5614 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); 5615 } 5616 #endif 5617 } 5618 /* Face vertices have 2 + cells*2 supports */ 5619 for(f = fStart; f < fEnd; ++f) { 5620 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5621 const PetscInt *cone, *support; 5622 PetscInt size, s; 5623 5624 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5625 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5626 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5627 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5628 for(s = 0; s < size; ++s) { 5629 PetscInt r = 0; 5630 5631 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5632 if (cone[1] == f) r = 1; 5633 else if (cone[2] == f) r = 2; 5634 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5635 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5636 } 5637 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5638 #if 1 5639 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5640 for(p = 0; p < 2+size*2; ++p) { 5641 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); 5642 } 5643 #endif 5644 } 5645 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5646 break; 5647 case 2: 5648 /* Hex 2D */ 5649 /* 5650 3---------2---------2 5651 | | | 5652 | D 2 C | 5653 | | | 5654 3----3----0----1----1 5655 | | | 5656 | A 0 B | 5657 | | | 5658 0---------0---------1 5659 */ 5660 /* All cells have 4 faces */ 5661 for(c = cStart; c < cEnd; ++c) { 5662 const PetscInt newp = (c - cStart)*4; 5663 const PetscInt *cone, *ornt; 5664 PetscInt coneNew[4], orntNew[4]; 5665 5666 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5667 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5668 /* A quad */ 5669 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5670 orntNew[0] = ornt[0]; 5671 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5672 orntNew[1] = 0; 5673 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5674 orntNew[2] = -2; 5675 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5676 orntNew[3] = ornt[3]; 5677 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5678 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5679 #if 1 5680 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); 5681 for(p = 0; p < 4; ++p) { 5682 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); 5683 } 5684 #endif 5685 /* B quad */ 5686 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5687 orntNew[0] = ornt[0]; 5688 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5689 orntNew[1] = ornt[1]; 5690 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5691 orntNew[2] = 0; 5692 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5693 orntNew[3] = -2; 5694 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5695 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5696 #if 1 5697 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); 5698 for(p = 0; p < 4; ++p) { 5699 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); 5700 } 5701 #endif 5702 /* C quad */ 5703 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5704 orntNew[0] = -2; 5705 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5706 orntNew[1] = ornt[1]; 5707 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5708 orntNew[2] = ornt[2]; 5709 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5710 orntNew[3] = 0; 5711 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5712 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5713 #if 1 5714 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); 5715 for(p = 0; p < 4; ++p) { 5716 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); 5717 } 5718 #endif 5719 /* D quad */ 5720 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5721 orntNew[0] = 0; 5722 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5723 orntNew[1] = -2; 5724 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5725 orntNew[2] = ornt[2]; 5726 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 5727 orntNew[3] = ornt[3]; 5728 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5729 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5730 #if 1 5731 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); 5732 for(p = 0; p < 4; ++p) { 5733 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); 5734 } 5735 #endif 5736 } 5737 /* Split faces have 2 vertices and the same cells as the parent */ 5738 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5739 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5740 for(f = fStart; f < fEnd; ++f) { 5741 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5742 5743 for(r = 0; r < 2; ++r) { 5744 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5745 const PetscInt *cone, *support; 5746 PetscInt coneNew[2], coneSize, c, supportSize, s; 5747 5748 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5749 coneNew[0] = vStartNew + (cone[0] - vStart); 5750 coneNew[1] = vStartNew + (cone[1] - vStart); 5751 coneNew[(r+1)%2] = newv; 5752 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5753 #if 1 5754 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5755 for(p = 0; p < 2; ++p) { 5756 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); 5757 } 5758 #endif 5759 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5760 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5761 for(s = 0; s < supportSize; ++s) { 5762 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5763 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5764 for(c = 0; c < coneSize; ++c) { 5765 if (cone[c] == f) { 5766 break; 5767 } 5768 } 5769 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 5770 } 5771 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5772 #if 1 5773 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5774 for(p = 0; p < supportSize; ++p) { 5775 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); 5776 } 5777 #endif 5778 } 5779 } 5780 /* Interior faces have 2 vertices and 2 cells */ 5781 for(c = cStart; c < cEnd; ++c) { 5782 const PetscInt *cone; 5783 PetscInt coneNew[2], supportNew[2]; 5784 5785 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5786 for(r = 0; r < 4; ++r) { 5787 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5788 5789 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5790 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5791 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5792 #if 1 5793 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5794 for(p = 0; p < 2; ++p) { 5795 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); 5796 } 5797 #endif 5798 supportNew[0] = (c - cStart)*4 + r; 5799 supportNew[1] = (c - cStart)*4 + (r+1)%4; 5800 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5801 #if 1 5802 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5803 for(p = 0; p < 2; ++p) { 5804 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); 5805 } 5806 #endif 5807 } 5808 } 5809 /* Old vertices have identical supports */ 5810 for(v = vStart; v < vEnd; ++v) { 5811 const PetscInt newp = vStartNew + (v - vStart); 5812 const PetscInt *support, *cone; 5813 PetscInt size, s; 5814 5815 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5816 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5817 for(s = 0; s < size; ++s) { 5818 PetscInt r = 0; 5819 5820 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5821 if (cone[1] == v) r = 1; 5822 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5823 } 5824 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5825 #if 1 5826 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5827 for(p = 0; p < size; ++p) { 5828 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); 5829 } 5830 #endif 5831 } 5832 /* Face vertices have 2 + cells supports */ 5833 for(f = fStart; f < fEnd; ++f) { 5834 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5835 const PetscInt *cone, *support; 5836 PetscInt size, s; 5837 5838 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5839 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5840 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5841 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5842 for(s = 0; s < size; ++s) { 5843 PetscInt r = 0; 5844 5845 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5846 if (cone[1] == f) r = 1; 5847 else if (cone[2] == f) r = 2; 5848 else if (cone[3] == f) r = 3; 5849 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 5850 } 5851 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5852 #if 1 5853 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5854 for(p = 0; p < 2+size; ++p) { 5855 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); 5856 } 5857 #endif 5858 } 5859 /* Cell vertices have 4 supports */ 5860 for(c = cStart; c < cEnd; ++c) { 5861 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5862 PetscInt supportNew[4]; 5863 5864 for(r = 0; r < 4; ++r) { 5865 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5866 } 5867 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5868 } 5869 break; 5870 default: 5871 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5872 } 5873 PetscFunctionReturn(0); 5874 } 5875 5876 #undef __FUNCT__ 5877 #define __FUNCT__ "CellRefinerSetCoordinates" 5878 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5879 { 5880 PetscSection coordSection, coordSectionNew; 5881 Vec coordinates, coordinatesNew; 5882 PetscScalar *coords, *coordsNew; 5883 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, f; 5884 PetscErrorCode ierr; 5885 5886 PetscFunctionBegin; 5887 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5888 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5889 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5890 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5891 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5892 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 5893 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5894 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 5895 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 5896 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 5897 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 5898 switch(refiner) { 5899 case 1: 5900 case 2: 5901 /* Simplicial and Hex 2D */ 5902 /* All vertices have the dim coordinates */ 5903 for(v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 5904 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 5905 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 5906 } 5907 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 5908 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 5909 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5910 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 5911 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 5912 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 5913 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 5914 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 5915 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 5916 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5917 /* Old vertices have the same coordinates */ 5918 for(v = vStart; v < vEnd; ++v) { 5919 const PetscInt newv = vStartNew + (v - vStart); 5920 PetscInt off, offnew, d; 5921 5922 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5923 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5924 for(d = 0; d < dim; ++d) { 5925 coordsNew[offnew+d] = coords[off+d]; 5926 } 5927 } 5928 /* Face vertices have the average of endpoint coordinates */ 5929 for(f = fStart; f < fEnd; ++f) { 5930 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5931 const PetscInt *cone; 5932 PetscInt coneSize, offA, offB, offnew, d; 5933 5934 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 5935 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 5936 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5937 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5938 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5939 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5940 for(d = 0; d < dim; ++d) { 5941 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 5942 } 5943 } 5944 /* Just Hex 2D */ 5945 if (refiner == 2) { 5946 /* Cell vertices have the average of corner coordinates */ 5947 for(c = cStart; c < cEnd; ++c) { 5948 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5949 PetscInt *cone = PETSC_NULL; 5950 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 5951 5952 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5953 for(p = 0; p < closureSize*2; p += 2) { 5954 const PetscInt point = cone[p]; 5955 if ((point >= vStart) && (point < vEnd)) { 5956 cone[coneSize++] = point; 5957 } 5958 } 5959 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 5960 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5961 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5962 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 5963 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 5964 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5965 for(d = 0; d < dim; ++d) { 5966 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 5967 } 5968 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5969 } 5970 } 5971 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 5972 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5973 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 5974 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 5975 break; 5976 default: 5977 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5978 } 5979 PetscFunctionReturn(0); 5980 } 5981 5982 #undef __FUNCT__ 5983 #define __FUNCT__ "DMPlexCreateProcessSF" 5984 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 5985 { 5986 PetscInt numRoots, numLeaves, l; 5987 const PetscInt *localPoints; 5988 const PetscSFNode *remotePoints; 5989 PetscInt *localPointsNew; 5990 PetscSFNode *remotePointsNew; 5991 PetscInt *ranks, *ranksNew; 5992 PetscErrorCode ierr; 5993 5994 PetscFunctionBegin; 5995 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5996 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 5997 for(l = 0; l < numLeaves; ++l) { 5998 ranks[l] = remotePoints[l].rank; 5999 } 6000 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6001 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6002 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6003 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6004 for(l = 0; l < numLeaves; ++l) { 6005 ranksNew[l] = ranks[l]; 6006 localPointsNew[l] = l; 6007 remotePointsNew[l].index = 0; 6008 remotePointsNew[l].rank = ranksNew[l]; 6009 } 6010 ierr = PetscFree(ranks);CHKERRQ(ierr); 6011 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6012 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6013 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6014 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6015 PetscFunctionReturn(0); 6016 } 6017 6018 #undef __FUNCT__ 6019 #define __FUNCT__ "CellRefinerCreateSF" 6020 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6021 { 6022 PetscSF sf, sfNew, sfProcess; 6023 IS processRanks; 6024 MPI_Datatype depthType; 6025 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6026 const PetscInt *localPoints, *neighbors; 6027 const PetscSFNode *remotePoints; 6028 PetscInt *localPointsNew; 6029 PetscSFNode *remotePointsNew; 6030 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6031 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, vStart, vStartNew, vEnd, fStart, fStartNew, fEnd, eStart, eStartNew, eEnd, r, n; 6032 PetscErrorCode ierr; 6033 6034 PetscFunctionBegin; 6035 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6036 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6037 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6038 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6039 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6040 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6041 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6042 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6043 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6044 /* Caculate size of new SF */ 6045 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6046 if (numRoots < 0) PetscFunctionReturn(0); 6047 for(l = 0; l < numLeaves; ++l) { 6048 const PetscInt p = localPoints[l]; 6049 6050 switch(refiner) { 6051 case 1: 6052 /* Simplicial 2D */ 6053 if ((p >= vStart) && (p < vEnd)) { 6054 /* Old vertices stay the same */ 6055 ++numLeavesNew; 6056 } else if ((p >= fStart) && (p < fEnd)) { 6057 /* Old faces add new faces and vertex */ 6058 numLeavesNew += 1 + 2; 6059 } else if ((p >= cStart) && (p < cEnd)) { 6060 /* Old cells add new cells and interior faces */ 6061 numLeavesNew += 4 + 3; 6062 } 6063 break; 6064 case 2: 6065 /* Hex 2D */ 6066 if ((p >= vStart) && (p < vEnd)) { 6067 /* Old vertices stay the same */ 6068 ++numLeavesNew; 6069 } else if ((p >= fStart) && (p < fEnd)) { 6070 /* Old faces add new faces and vertex */ 6071 numLeavesNew += 1 + 2; 6072 } else if ((p >= cStart) && (p < cEnd)) { 6073 /* Old cells add new cells and interior faces */ 6074 numLeavesNew += 4 + 4; 6075 } 6076 break; 6077 default: 6078 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6079 } 6080 } 6081 /* Communicate depthSizes for each remote rank */ 6082 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6083 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6084 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6085 ierr = PetscMalloc6(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr); 6086 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6087 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6088 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6089 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6090 for(n = 0; n < numNeighbors; ++n) { 6091 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6092 } 6093 depthSizeOld[depth] = cEnd - cStart; 6094 depthSizeOld[0] = vEnd - vStart; 6095 depthSizeOld[depth-1] = fEnd - fStart; 6096 depthSizeOld[1] = eEnd - eStart; 6097 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6098 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6099 for(n = 0; n < numNeighbors; ++n) { 6100 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6101 } 6102 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6103 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6104 /* Calculate new point SF */ 6105 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6106 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6107 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6108 for(l = 0, m = 0; l < numLeaves; ++l) { 6109 PetscInt p = localPoints[l]; 6110 PetscInt rp = remotePoints[l].index, n; 6111 PetscMPIInt rrank = remotePoints[l].rank; 6112 6113 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6114 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6115 switch(refiner) { 6116 case 1: 6117 /* Simplicial 2D */ 6118 if ((p >= vStart) && (p < vEnd)) { 6119 /* Old vertices stay the same */ 6120 localPointsNew[m] = vStartNew + (p - vStart); 6121 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6122 remotePointsNew[m].rank = rrank; 6123 ++m; 6124 } else if ((p >= fStart) && (p < fEnd)) { 6125 /* Old faces add new faces and vertex */ 6126 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6127 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6128 remotePointsNew[m].rank = rrank; 6129 ++m; 6130 for(r = 0; r < 2; ++r, ++m) { 6131 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6132 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6133 remotePointsNew[m].rank = rrank; 6134 } 6135 } else if ((p >= cStart) && (p < cEnd)) { 6136 /* Old cells add new cells and interior faces */ 6137 for(r = 0; r < 4; ++r, ++m) { 6138 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6139 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6140 remotePointsNew[m].rank = rrank; 6141 } 6142 for(r = 0; r < 3; ++r, ++m) { 6143 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6144 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6145 remotePointsNew[m].rank = rrank; 6146 } 6147 } 6148 break; 6149 case 2: 6150 /* Hex 2D */ 6151 if ((p >= vStart) && (p < vEnd)) { 6152 /* Old vertices stay the same */ 6153 localPointsNew[m] = vStartNew + (p - vStart); 6154 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6155 remotePointsNew[m].rank = rrank; 6156 ++m; 6157 } else if ((p >= fStart) && (p < fEnd)) { 6158 /* Old faces add new faces and vertex */ 6159 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6160 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6161 remotePointsNew[m].rank = rrank; 6162 ++m; 6163 for(r = 0; r < 2; ++r, ++m) { 6164 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6165 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6166 remotePointsNew[m].rank = rrank; 6167 } 6168 } else if ((p >= cStart) && (p < cEnd)) { 6169 /* Old cells add new cells and interior faces */ 6170 for(r = 0; r < 4; ++r, ++m) { 6171 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6172 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6173 remotePointsNew[m].rank = rrank; 6174 } 6175 for(r = 0; r < 4; ++r, ++m) { 6176 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6177 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6178 remotePointsNew[m].rank = rrank; 6179 } 6180 } 6181 break; 6182 default: 6183 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6184 } 6185 } 6186 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6187 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6188 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6189 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6190 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6191 PetscFunctionReturn(0); 6192 } 6193 6194 #undef __FUNCT__ 6195 #define __FUNCT__ "CellRefinerCreateLabels" 6196 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6197 { 6198 PetscInt numLabels, l; 6199 PetscInt newp, cStart, cEnd, vStart, vStartNew, vEnd, fStart, fStartNew, fEnd, eStart, eEnd, r; 6200 PetscErrorCode ierr; 6201 6202 PetscFunctionBegin; 6203 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6204 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6205 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6206 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6207 vStartNew = depthSize[2]; 6208 fStartNew = depthSize[2] + depthSize[0]; 6209 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6210 for(l = 0; l < numLabels; ++l) { 6211 DMLabel label, labelNew; 6212 const char *lname; 6213 PetscBool isDepth; 6214 IS valueIS; 6215 const PetscInt *values; 6216 PetscInt numValues, val; 6217 6218 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6219 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6220 if (isDepth) continue; 6221 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6222 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6223 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6224 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6225 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6226 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6227 for(val = 0; val < numValues; ++val) { 6228 IS pointIS; 6229 const PetscInt *points; 6230 PetscInt numPoints, n; 6231 6232 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6233 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6234 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6235 for(n = 0; n < numPoints; ++n) { 6236 const PetscInt p = points[n]; 6237 switch(refiner) { 6238 case 1: 6239 /* Simplicial 2D */ 6240 if ((p >= vStart) && (p < vEnd)) { 6241 /* Old vertices stay the same */ 6242 newp = vStartNew + (p - vStart); 6243 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6244 } else if ((p >= fStart) && (p < fEnd)) { 6245 /* Old faces add new faces and vertex */ 6246 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6247 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6248 for(r = 0; r < 2; ++r) { 6249 newp = fStartNew + (p - fStart)*2 + r; 6250 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6251 } 6252 } else if ((p >= cStart) && (p < cEnd)) { 6253 /* Old cells add new cells and interior faces */ 6254 for(r = 0; r < 4; ++r) { 6255 newp = (p - cStart)*4 + r; 6256 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6257 } 6258 for(r = 0; r < 3; ++r) { 6259 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6260 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6261 } 6262 } 6263 break; 6264 case 2: 6265 /* Hex 2D */ 6266 if ((p >= vStart) && (p < vEnd)) { 6267 /* Old vertices stay the same */ 6268 newp = vStartNew + (p - vStart); 6269 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6270 } else if ((p >= fStart) && (p < fEnd)) { 6271 /* Old faces add new faces and vertex */ 6272 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6273 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6274 for(r = 0; r < 2; ++r) { 6275 newp = fStartNew + (p - fStart)*2 + r; 6276 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6277 } 6278 } else if ((p >= cStart) && (p < cEnd)) { 6279 /* Old cells add new cells and interior faces and vertex */ 6280 for(r = 0; r < 4; ++r) { 6281 newp = (p - cStart)*4 + r; 6282 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6283 } 6284 for(r = 0; r < 4; ++r) { 6285 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6286 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6287 } 6288 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 6289 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6290 } 6291 break; 6292 default: 6293 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6294 } 6295 } 6296 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 6297 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 6298 } 6299 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 6300 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 6301 if (0) { 6302 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 6303 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6304 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6305 } 6306 } 6307 PetscFunctionReturn(0); 6308 } 6309 6310 #undef __FUNCT__ 6311 #define __FUNCT__ "DMPlexRefine_Uniform" 6312 /* This will only work for interpolated meshes */ 6313 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 6314 { 6315 DM rdm; 6316 PetscInt *depthSize; 6317 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 6318 PetscErrorCode ierr; 6319 6320 PetscFunctionBegin; 6321 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 6322 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 6323 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6324 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 6325 /* Calculate number of new points of each depth */ 6326 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6327 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 6328 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 6329 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 6330 /* Step 1: Set chart */ 6331 for(d = 0; d <= depth; ++d) { 6332 pEnd += depthSize[d]; 6333 } 6334 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 6335 /* Step 2: Set cone/support sizes */ 6336 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6337 /* Step 3: Setup refined DM */ 6338 ierr = DMSetUp(rdm);CHKERRQ(ierr); 6339 /* Step 4: Set cones and supports */ 6340 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6341 /* Step 5: Stratify */ 6342 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 6343 /* Step 6: Set coordinates for vertices */ 6344 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6345 /* Step 7: Create pointSF */ 6346 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6347 /* Step 8: Create labels */ 6348 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6349 ierr = PetscFree(depthSize);CHKERRQ(ierr); 6350 6351 *dmRefined = rdm; 6352 #if 0 6353 DM_Plex *mesh = (DM_Plex *) dm->data; 6354 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 6355 //ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); 6356 6357 PetscFunctionBegin; 6358 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6359 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 6360 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6361 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6362 ierr = DMPlexGetVTKBounds(dm, &cMax, &vMax);CHKERRQ(ierr); 6363 6364 /* Count number of new cells which are normal and extra */ 6365 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 6366 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 6367 for(c = cStart; c < cEnd2; ++c) { 6368 PetscInt n; 6369 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); // refiner.numNewCells 6370 newNumCellsNormal += n; 6371 } 6372 for(c = cEnd2; c < cEnd; ++c) { 6373 PetscInt n; 6374 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); // refiner.numNewCells 6375 newNumCellsExtra += n; 6376 } 6377 newNumCells = newNumCellsNormal + newNumCellsExtra; 6378 /* Count number of new vertices which are normal and extra */ 6379 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 6380 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 6381 for(c = cStart; c < cEnd; ++c) { 6382 PetscInt *closure = PETSC_NULL; 6383 PetscInt closureSize, numCorners = 0, p; 6384 6385 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6386 for(p = 0; p < closureSize*2; p += 2) { 6387 const PetscInt point = closure[p]; 6388 if ((point >= vStart) && (point < vEnd)) { 6389 closure[numCorners++] = point; 6390 } 6391 } 6392 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); // refiner.splitCell 6393 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6394 } 6395 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 6396 for(c = cEnd2; c < cEnd; ++c) { 6397 PetscInt *closure = PETSC_NULL; 6398 PetscInt closureSize, numCorners = 0, p; 6399 6400 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6401 for(p = 0; p < closureSize*2; p += 2) { 6402 const PetscInt point = closure[p]; 6403 if ((point >= vStart) && (point < vEnd)) { 6404 closure[numCorners++] = point; 6405 } 6406 } 6407 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); // refiner.splitCellUncensored 6408 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6409 } // for 6410 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 6411 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 6412 6413 #if 1 6414 PetscInt oldNumCellsNormal = cEnd2 - cStart; 6415 PetscInt oldNumCellsExtra = cEnd - cEnd2; 6416 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 6417 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 6418 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 6419 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 6420 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 6421 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 6422 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 6423 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 6424 ierr = PetscSynchronizedFlush(comm); 6425 #endif 6426 6427 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 6428 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 6429 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 6430 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 6431 ierr = DMPlexGetVTKBounds(*dmRefined, newNumCellsNormal, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 6432 /* Set cone and support sizes for new normal cells */ 6433 PetscInt newCell = 0; 6434 for(c = cStart; c < cEnd2; ++c) { 6435 PetscInt coneSize, n, i; 6436 6437 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6438 ierr = CellRefinerGetNumSubcells(refiner, c, &n); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6439 for(i = 0; i < n; ++i, ++newCell) { 6440 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 6441 } 6442 6443 PetscInt *closure = PETSC_NULL; 6444 PetscInt closureSize, numCorners = 0, p; 6445 6446 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6447 for(p = 0; p < closureSize*2; p += 2) { 6448 const PetscInt point = closure[p]; 6449 if ((point >= vStart) && (point < vEnd)) { 6450 closure[numCorners++] = point; 6451 } 6452 } 6453 // ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6454 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6455 } 6456 6457 // Reset current new cell value and loop over censored cells. 6458 curNewCell = _orderNewMesh->cellsCensored().min(); 6459 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 6460 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 6461 // Set new cone and support sizes 6462 cV.clear(); 6463 sieve->cone(*c_iter, cV); 6464 const point_type* cone = cV.getPoints(); 6465 const int coneSize = cV.getSize(); 6466 6467 const point_type* newCells; 6468 int numNewCells = 0; 6469 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6470 6471 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 6472 newSieve->setConeSize(curNewCell, coneSize); 6473 for(int iVertex=0; iVertex < coneSize; ++iVertex) { 6474 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 6475 } // for 6476 } // for 6477 } // for 6478 newSieve->allocate(); 6479 6480 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 6481 6482 // Create refined cells in new sieve. 6483 curNewCell = _orderNewMesh->cellsNormal().min(); 6484 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 6485 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 6486 cV.clear(); 6487 sieve->cone(*c_iter, cV); 6488 const point_type *cone = cV.getPoints(); 6489 const int coneSize = cV.getSize(); 6490 6491 const point_type* newCells; 6492 int numNewCells = 0; 6493 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6494 6495 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 6496 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 6497 } // for 6498 } // for 6499 curNewCell = _orderNewMesh->cellsCensored().min(); 6500 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 6501 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 6502 cV.clear(); 6503 sieve->cone(*c_iter, cV); 6504 const point_type *cone = cV.getPoints(); 6505 const int coneSize = cV.getSize(); 6506 6507 const point_type* newCells; 6508 int numNewCells = 0; 6509 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6510 6511 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 6512 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 6513 } // for 6514 } // for 6515 newSieve->symmetrize(); 6516 6517 // Set coordinates in refined mesh. 6518 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 6519 assert(!coordinates.isNull()); 6520 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 6521 assert(!newCoordinates.isNull()); 6522 6523 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 6524 assert(vertices->size() > 0); 6525 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 6526 assert(spaceDim > 0); 6527 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 6528 6529 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 6530 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 6531 newCoordinates->setFiberDimension(*v_iter, spaceDim); 6532 } // for 6533 newCoordinates->allocatePoint(); 6534 6535 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 6536 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 6537 //std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; 6538 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 6539 } // for 6540 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 6541 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 6542 //std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; 6543 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 6544 } // for 6545 6546 refiner.setCoordsNewVertices(newCoordinates, coordinates); 6547 6548 // Create sensored depth 6549 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 6550 assert(!censoredLabel.isNull()); 6551 6552 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 6553 6554 newSieve->roots(depthVisitor); 6555 while(depthVisitor.isModified()) { 6556 // FIX: Avoid the copy here somehow by fixing the traversal 6557 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 6558 6559 depthVisitor.clear(); 6560 newSieve->support(modifiedPoints, depthVisitor); 6561 } // while 6562 // Stratify refined mesh 6563 // Calculate new point SF 6564 _calcNewOverlap(newMesh, mesh, refiner); 6565 // Calculate new labels 6566 _createLabels(newMesh, mesh, refiner); 6567 #endif 6568 PetscFunctionReturn(0); 6569 } 6570 6571 #undef __FUNCT__ 6572 #define __FUNCT__ "DMPlexSetRefinementUniform" 6573 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 6574 { 6575 DM_Plex *mesh = (DM_Plex *) dm->data; 6576 6577 PetscFunctionBegin; 6578 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6579 mesh->refinementUniform = refinementUniform; 6580 PetscFunctionReturn(0); 6581 } 6582 6583 #undef __FUNCT__ 6584 #define __FUNCT__ "DMPlexGetRefinementUniform" 6585 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 6586 { 6587 DM_Plex *mesh = (DM_Plex *) dm->data; 6588 6589 PetscFunctionBegin; 6590 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6591 PetscValidPointer(refinementUniform, 2); 6592 *refinementUniform = mesh->refinementUniform; 6593 PetscFunctionReturn(0); 6594 } 6595 6596 #undef __FUNCT__ 6597 #define __FUNCT__ "DMPlexSetRefinementLimit" 6598 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 6599 { 6600 DM_Plex *mesh = (DM_Plex *) dm->data; 6601 6602 PetscFunctionBegin; 6603 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6604 mesh->refinementLimit = refinementLimit; 6605 PetscFunctionReturn(0); 6606 } 6607 6608 #undef __FUNCT__ 6609 #define __FUNCT__ "DMPlexGetRefinementLimit" 6610 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 6611 { 6612 DM_Plex *mesh = (DM_Plex *) dm->data; 6613 6614 PetscFunctionBegin; 6615 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6616 PetscValidPointer(refinementLimit, 2); 6617 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 6618 *refinementLimit = mesh->refinementLimit; 6619 PetscFunctionReturn(0); 6620 } 6621 6622 #undef __FUNCT__ 6623 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 6624 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 6625 { 6626 PetscInt dim, cStart, coneSize; 6627 PetscErrorCode ierr; 6628 6629 PetscFunctionBegin; 6630 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6631 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 6632 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 6633 switch(dim) { 6634 case 2: 6635 switch(coneSize) { 6636 case 3: 6637 *cellRefiner = 1;break; 6638 case 4: 6639 *cellRefiner = 2;break; 6640 default: 6641 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 6642 } 6643 break; 6644 default: 6645 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 6646 } 6647 PetscFunctionReturn(0); 6648 } 6649 6650 #undef __FUNCT__ 6651 #define __FUNCT__ "DMRefine_Plex" 6652 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 6653 { 6654 PetscReal refinementLimit; 6655 PetscInt dim, cStart, cEnd; 6656 char genname[1024], *name = PETSC_NULL; 6657 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 6658 PetscErrorCode ierr; 6659 6660 PetscFunctionBegin; 6661 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 6662 if (isUniform) { 6663 CellRefiner cellRefiner; 6664 6665 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 6666 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 6667 PetscFunctionReturn(0); 6668 } 6669 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 6670 if (refinementLimit == 0.0) PetscFunctionReturn(0); 6671 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6672 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6673 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 6674 if (flg) {name = genname;} 6675 if (name) { 6676 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 6677 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 6678 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 6679 } 6680 switch(dim) { 6681 case 2: 6682 if (!name || isTriangle) { 6683 #ifdef PETSC_HAVE_TRIANGLE 6684 double *maxVolumes; 6685 PetscInt c; 6686 6687 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 6688 for (c = 0; c < cEnd-cStart; ++c) { 6689 maxVolumes[c] = refinementLimit; 6690 } 6691 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 6692 #else 6693 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 6694 #endif 6695 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 6696 break; 6697 case 3: 6698 if (!name || isCTetgen) { 6699 #ifdef PETSC_HAVE_CTETGEN 6700 PetscReal *maxVolumes; 6701 PetscInt c; 6702 6703 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 6704 for (c = 0; c < cEnd-cStart; ++c) { 6705 maxVolumes[c] = refinementLimit; 6706 } 6707 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 6708 #else 6709 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 6710 #endif 6711 } else if (isTetgen) { 6712 #ifdef PETSC_HAVE_TETGEN 6713 double *maxVolumes; 6714 PetscInt c; 6715 6716 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 6717 for (c = 0; c < cEnd-cStart; ++c) { 6718 maxVolumes[c] = refinementLimit; 6719 } 6720 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 6721 #else 6722 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 6723 #endif 6724 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 6725 break; 6726 default: 6727 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 6728 } 6729 PetscFunctionReturn(0); 6730 } 6731 6732 #undef __FUNCT__ 6733 #define __FUNCT__ "DMPlexGetDepth" 6734 /*@ 6735 DMPlexGetDepth - get the number of strata 6736 6737 Not Collective 6738 6739 Input Parameters: 6740 . dm - The DMPlex object 6741 6742 Output Parameters: 6743 . depth - number of strata 6744 6745 Level: developer 6746 6747 Notes: 6748 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 6749 6750 .keywords: mesh, points 6751 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 6752 @*/ 6753 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 6754 { 6755 PetscInt d; 6756 PetscErrorCode ierr; 6757 6758 PetscFunctionBegin; 6759 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6760 PetscValidPointer(depth, 2); 6761 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 6762 *depth = d-1; 6763 PetscFunctionReturn(0); 6764 } 6765 6766 #undef __FUNCT__ 6767 #define __FUNCT__ "DMPlexGetDepthStratum" 6768 /*@ 6769 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 6770 6771 Not Collective 6772 6773 Input Parameters: 6774 + dm - The DMPlex object 6775 - stratumValue - The requested depth 6776 6777 Output Parameters: 6778 + start - The first point at this depth 6779 - end - One beyond the last point at this depth 6780 6781 Level: developer 6782 6783 .keywords: mesh, points 6784 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 6785 @*/ 6786 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) { 6787 DM_Plex *mesh = (DM_Plex *) dm->data; 6788 DMLabel next = mesh->labels; 6789 PetscBool flg = PETSC_FALSE; 6790 PetscInt depth; 6791 PetscErrorCode ierr; 6792 6793 PetscFunctionBegin; 6794 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6795 if (stratumValue < 0) { 6796 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 6797 PetscFunctionReturn(0); 6798 } else { 6799 PetscInt pStart, pEnd; 6800 6801 if (start) {*start = 0;} 6802 if (end) {*end = 0;} 6803 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6804 if (pStart == pEnd) {PetscFunctionReturn(0);} 6805 } 6806 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6807 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6808 /* We should have a generic GetLabel() and a Label class */ 6809 while(next) { 6810 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6811 if (flg) break; 6812 next = next->next; 6813 } 6814 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6815 depth = stratumValue; 6816 if ((depth < 0) || (depth >= next->numStrata)) { 6817 if (start) {*start = 0;} 6818 if (end) {*end = 0;} 6819 } else { 6820 if (start) {*start = next->points[next->stratumOffsets[depth]];} 6821 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 6822 } 6823 PetscFunctionReturn(0); 6824 } 6825 6826 #undef __FUNCT__ 6827 #define __FUNCT__ "DMPlexGetHeightStratum" 6828 /*@ 6829 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 6830 6831 Not Collective 6832 6833 Input Parameters: 6834 + dm - The DMPlex object 6835 - stratumValue - The requested height 6836 6837 Output Parameters: 6838 + start - The first point at this height 6839 - end - One beyond the last point at this height 6840 6841 Level: developer 6842 6843 .keywords: mesh, points 6844 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 6845 @*/ 6846 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) { 6847 DM_Plex *mesh = (DM_Plex *) dm->data; 6848 DMLabel next = mesh->labels; 6849 PetscBool flg = PETSC_FALSE; 6850 PetscInt depth; 6851 PetscErrorCode ierr; 6852 6853 PetscFunctionBegin; 6854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6855 if (stratumValue < 0) { 6856 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 6857 } else { 6858 PetscInt pStart, pEnd; 6859 6860 if (start) {*start = 0;} 6861 if (end) {*end = 0;} 6862 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6863 if (pStart == pEnd) {PetscFunctionReturn(0);} 6864 } 6865 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6866 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6867 /* We should have a generic GetLabel() and a Label class */ 6868 while(next) { 6869 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6870 if (flg) break; 6871 next = next->next; 6872 } 6873 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6874 depth = next->stratumValues[next->numStrata-1] - stratumValue; 6875 if ((depth < 0) || (depth >= next->numStrata)) { 6876 if (start) {*start = 0;} 6877 if (end) {*end = 0;} 6878 } else { 6879 if (start) {*start = next->points[next->stratumOffsets[depth]];} 6880 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 6881 } 6882 PetscFunctionReturn(0); 6883 } 6884 6885 #undef __FUNCT__ 6886 #define __FUNCT__ "DMPlexCreateSectionInitial" 6887 /* Set the number of dof on each point and separate by fields */ 6888 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) { 6889 PetscInt *numDofTot; 6890 PetscInt pStart = 0, pEnd = 0; 6891 PetscInt p, d, f; 6892 PetscErrorCode ierr; 6893 6894 PetscFunctionBegin; 6895 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 6896 for(d = 0; d <= dim; ++d) { 6897 numDofTot[d] = 0; 6898 for(f = 0; f < numFields; ++f) { 6899 numDofTot[d] += numDof[f*(dim+1)+d]; 6900 } 6901 } 6902 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 6903 if (numFields > 0) { 6904 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 6905 if (numComp) { 6906 for(f = 0; f < numFields; ++f) { 6907 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 6908 } 6909 } 6910 } 6911 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6912 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 6913 for(d = 0; d <= dim; ++d) { 6914 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 6915 for(p = pStart; p < pEnd; ++p) { 6916 for(f = 0; f < numFields; ++f) { 6917 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 6918 } 6919 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 6920 } 6921 } 6922 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 6923 PetscFunctionReturn(0); 6924 } 6925 6926 #undef __FUNCT__ 6927 #define __FUNCT__ "DMPlexCreateSectionBCDof" 6928 /* Set the number of dof on each point and separate by fields 6929 If constDof is PETSC_DETERMINE, constrain every dof on the point 6930 */ 6931 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) { 6932 PetscInt numFields; 6933 PetscInt bc; 6934 PetscErrorCode ierr; 6935 6936 PetscFunctionBegin; 6937 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6938 for (bc = 0; bc < numBC; ++bc) { 6939 PetscInt field = 0; 6940 const PetscInt *idx; 6941 PetscInt n, i; 6942 6943 if (numFields) {field = bcField[bc];} 6944 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 6945 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6946 for (i = 0; i < n; ++i) { 6947 const PetscInt p = idx[i]; 6948 PetscInt numConst = constDof; 6949 6950 /* Constrain every dof on the point */ 6951 if (numConst < 0) { 6952 if (numFields) { 6953 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 6954 } else { 6955 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 6956 } 6957 } 6958 if (numFields) { 6959 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 6960 } 6961 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 6962 } 6963 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6964 } 6965 PetscFunctionReturn(0); 6966 } 6967 6968 #undef __FUNCT__ 6969 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 6970 /* Set the constrained indices on each point and separate by fields */ 6971 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) { 6972 PetscInt *maxConstraints; 6973 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 6974 PetscErrorCode ierr; 6975 6976 PetscFunctionBegin; 6977 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6978 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6979 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 6980 for(f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 6981 for(p = pStart; p < pEnd; ++p) { 6982 PetscInt cdof; 6983 6984 if (numFields) { 6985 for(f = 0; f < numFields; ++f) { 6986 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 6987 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 6988 } 6989 } else { 6990 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6991 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 6992 } 6993 } 6994 for (f = 0; f < numFields; ++f) { 6995 maxConstraints[numFields] += maxConstraints[f]; 6996 } 6997 if (maxConstraints[numFields]) { 6998 PetscInt *indices; 6999 7000 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7001 for (p = pStart; p < pEnd; ++p) { 7002 PetscInt cdof, d; 7003 7004 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7005 if (cdof) { 7006 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7007 if (numFields) { 7008 PetscInt numConst = 0, foff = 0; 7009 7010 for (f = 0; f < numFields; ++f) { 7011 PetscInt cfdof, fdof; 7012 7013 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7014 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7015 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7016 for(d = 0; d < cfdof; ++d) { 7017 indices[numConst+d] = d; 7018 } 7019 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7020 for(d = 0; d < cfdof; ++d) { 7021 indices[numConst+d] += foff; 7022 } 7023 numConst += cfdof; 7024 foff += fdof; 7025 } 7026 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7027 } else { 7028 for (d = 0; d < cdof; ++d) { 7029 indices[d] = d; 7030 } 7031 } 7032 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7033 } 7034 } 7035 ierr = PetscFree(indices);CHKERRQ(ierr); 7036 } 7037 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7038 PetscFunctionReturn(0); 7039 } 7040 7041 #undef __FUNCT__ 7042 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7043 /* Set the constrained field indices on each point */ 7044 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) { 7045 const PetscInt *points, *indices; 7046 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7047 PetscErrorCode ierr; 7048 7049 PetscFunctionBegin; 7050 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7051 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7052 7053 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7054 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7055 if (!constraintIndices) { 7056 PetscInt *idx, i; 7057 7058 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7059 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7060 for(i = 0; i < maxDof; ++i) {idx[i] = i;} 7061 for(p = 0; p < numPoints; ++p) { 7062 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7063 } 7064 ierr = PetscFree(idx);CHKERRQ(ierr); 7065 } else { 7066 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7067 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7068 for(p = 0; p < numPoints; ++p) { 7069 PetscInt fcdof; 7070 7071 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7072 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); 7073 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7074 } 7075 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7076 } 7077 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7078 PetscFunctionReturn(0); 7079 } 7080 7081 #undef __FUNCT__ 7082 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7083 /* Set the constrained indices on each point and separate by fields */ 7084 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) { 7085 PetscInt *indices; 7086 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7087 PetscErrorCode ierr; 7088 7089 PetscFunctionBegin; 7090 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7091 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7092 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7093 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7094 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7095 for (p = pStart; p < pEnd; ++p) { 7096 PetscInt cdof, d; 7097 7098 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7099 if (cdof) { 7100 PetscInt numConst = 0, foff = 0; 7101 7102 for (f = 0; f < numFields; ++f) { 7103 const PetscInt *fcind; 7104 PetscInt fdof, fcdof; 7105 7106 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7107 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7108 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7109 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7110 for(d = 0; d < fcdof; ++d) { 7111 indices[numConst+d] = fcind[d]+foff; 7112 } 7113 foff += fdof; 7114 numConst += fcdof; 7115 } 7116 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7117 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7118 } 7119 } 7120 ierr = PetscFree(indices);CHKERRQ(ierr); 7121 PetscFunctionReturn(0); 7122 } 7123 7124 #undef __FUNCT__ 7125 #define __FUNCT__ "DMPlexCreateSection" 7126 /*@C 7127 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7128 7129 Not Collective 7130 7131 Input Parameters: 7132 + dm - The DMPlex object 7133 . dim - The spatial dimension of the problem 7134 . numFields - The number of fields in the problem 7135 . numComp - An array of size numFields that holds the number of components for each field 7136 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7137 . numBC - The number of boundary conditions 7138 . bcField - An array of size numBC giving the field number for each boundry condition 7139 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7140 7141 Output Parameter: 7142 . section - The PetscSection object 7143 7144 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 7145 nubmer of dof for field 0 on each edge. 7146 7147 Level: developer 7148 7149 .keywords: mesh, elements 7150 .seealso: DMPlexCreate(), PetscSectionCreate() 7151 @*/ 7152 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) { 7153 PetscErrorCode ierr; 7154 7155 PetscFunctionBegin; 7156 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7157 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7158 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7159 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7160 { 7161 PetscBool view = PETSC_FALSE; 7162 7163 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7164 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7165 } 7166 PetscFunctionReturn(0); 7167 } 7168 7169 #undef __FUNCT__ 7170 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7171 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) { 7172 PetscSection section; 7173 PetscErrorCode ierr; 7174 7175 PetscFunctionBegin; 7176 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7177 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 7178 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7179 PetscFunctionReturn(0); 7180 } 7181 7182 #undef __FUNCT__ 7183 #define __FUNCT__ "DMPlexGetCoordinateSection" 7184 /*@ 7185 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7186 7187 Not Collective 7188 7189 Input Parameter: 7190 . dm - The DMPlex object 7191 7192 Output Parameter: 7193 . section - The PetscSection object 7194 7195 Level: intermediate 7196 7197 .keywords: mesh, coordinates 7198 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7199 @*/ 7200 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) { 7201 DM cdm; 7202 PetscErrorCode ierr; 7203 7204 PetscFunctionBegin; 7205 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7206 PetscValidPointer(section, 2); 7207 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7208 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7209 PetscFunctionReturn(0); 7210 } 7211 7212 #undef __FUNCT__ 7213 #define __FUNCT__ "DMPlexSetCoordinateSection" 7214 /*@ 7215 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7216 7217 Not Collective 7218 7219 Input Parameters: 7220 + dm - The DMPlex object 7221 - section - The PetscSection object 7222 7223 Level: intermediate 7224 7225 .keywords: mesh, coordinates 7226 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7227 @*/ 7228 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) { 7229 DM cdm; 7230 PetscErrorCode ierr; 7231 7232 PetscFunctionBegin; 7233 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7234 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7235 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7236 PetscFunctionReturn(0); 7237 } 7238 7239 #undef __FUNCT__ 7240 #define __FUNCT__ "DMPlexGetConeSection" 7241 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) { 7242 DM_Plex *mesh = (DM_Plex *) dm->data; 7243 7244 PetscFunctionBegin; 7245 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7246 if (section) *section = mesh->coneSection; 7247 PetscFunctionReturn(0); 7248 } 7249 7250 #undef __FUNCT__ 7251 #define __FUNCT__ "DMPlexGetCones" 7252 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) { 7253 DM_Plex *mesh = (DM_Plex *) dm->data; 7254 7255 PetscFunctionBegin; 7256 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7257 if (cones) *cones = mesh->cones; 7258 PetscFunctionReturn(0); 7259 } 7260 7261 #undef __FUNCT__ 7262 #define __FUNCT__ "DMPlexGetConeOrientations" 7263 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) { 7264 DM_Plex *mesh = (DM_Plex *) dm->data; 7265 7266 PetscFunctionBegin; 7267 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7268 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7269 PetscFunctionReturn(0); 7270 } 7271 7272 #undef __FUNCT__ 7273 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7274 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7275 { 7276 const PetscInt embedDim = 2; 7277 PetscReal x = PetscRealPart(point[0]); 7278 PetscReal y = PetscRealPart(point[1]); 7279 PetscReal v0[2], J[4], invJ[4], detJ; 7280 PetscReal xi, eta; 7281 PetscErrorCode ierr; 7282 7283 PetscFunctionBegin; 7284 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7285 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7286 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7287 7288 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 7289 *cell = c; 7290 } else { 7291 *cell = -1; 7292 } 7293 PetscFunctionReturn(0); 7294 } 7295 7296 #undef __FUNCT__ 7297 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7298 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7299 { 7300 PetscSection coordSection; 7301 Vec coordsLocal; 7302 const PetscScalar *coords; 7303 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7304 PetscReal x = PetscRealPart(point[0]); 7305 PetscReal y = PetscRealPart(point[1]); 7306 PetscInt crossings = 0, f; 7307 PetscErrorCode ierr; 7308 7309 PetscFunctionBegin; 7310 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7311 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7312 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7313 for(f = 0; f < 4; ++f) { 7314 PetscReal x_i = coords[faces[2*f+0]*2+0]; 7315 PetscReal y_i = coords[faces[2*f+0]*2+1]; 7316 PetscReal x_j = coords[faces[2*f+1]*2+0]; 7317 PetscReal y_j = coords[faces[2*f+1]*2+1]; 7318 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7319 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7320 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7321 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7322 if ((cond1 || cond2) && above) ++crossings; 7323 } 7324 if (crossings % 2) { 7325 *cell = c; 7326 } else { 7327 *cell = -1; 7328 } 7329 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7330 PetscFunctionReturn(0); 7331 } 7332 7333 #undef __FUNCT__ 7334 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7335 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7336 { 7337 const PetscInt embedDim = 3; 7338 PetscReal v0[3], J[9], invJ[9], detJ; 7339 PetscReal x = PetscRealPart(point[0]); 7340 PetscReal y = PetscRealPart(point[1]); 7341 PetscReal z = PetscRealPart(point[2]); 7342 PetscReal xi, eta, zeta; 7343 PetscErrorCode ierr; 7344 7345 PetscFunctionBegin; 7346 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7347 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7348 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7349 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7350 7351 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 7352 *cell = c; 7353 } else { 7354 *cell = -1; 7355 } 7356 PetscFunctionReturn(0); 7357 } 7358 7359 #undef __FUNCT__ 7360 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7361 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7362 { 7363 PetscSection coordSection; 7364 Vec coordsLocal; 7365 const PetscScalar *coords; 7366 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7367 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7368 PetscReal x = PetscRealPart(point[0]); 7369 PetscReal y = PetscRealPart(point[1]); 7370 PetscReal z = PetscRealPart(point[2]); 7371 PetscBool found = PETSC_TRUE; 7372 PetscInt f; 7373 PetscErrorCode ierr; 7374 7375 PetscFunctionBegin; 7376 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7377 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7378 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7379 for(f = 0; f < 6; ++f) { 7380 /* Check the point is under plane */ 7381 /* Get face normal */ 7382 PetscReal v_i[3] = {coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]}; 7383 PetscReal v_j[3] = {coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]}; 7384 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]}; 7385 PetscReal pp[3] = {coords[faces[f*4+0]*3+0] - x,coords[faces[f*4+0]*3+1] - y,coords[faces[f*4+0]*3+2] - z}; 7386 PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7387 /* Check that projected point is in face (2D location problem) */ 7388 if (dot < 0.0) { 7389 found = PETSC_FALSE; 7390 break; 7391 } 7392 } 7393 if (found) { 7394 *cell = c; 7395 } else { 7396 *cell = -1; 7397 } 7398 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7399 PetscFunctionReturn(0); 7400 } 7401 7402 #undef __FUNCT__ 7403 #define __FUNCT__ "DMLocatePoints_Plex" 7404 /* 7405 Need to implement using the guess 7406 */ 7407 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7408 { 7409 PetscInt cell = -1/*, guess = -1*/; 7410 PetscInt bs, numPoints, p; 7411 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7412 PetscInt *cells; 7413 PetscScalar *a; 7414 PetscErrorCode ierr; 7415 7416 PetscFunctionBegin; 7417 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7418 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7419 ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr); 7420 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7421 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7422 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7423 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); 7424 numPoints /= bs; 7425 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7426 for(p = 0; p < numPoints; ++p) { 7427 const PetscScalar *point = &a[p*bs]; 7428 7429 switch(dim) { 7430 case 2: 7431 for(c = cStart; c < cEnd; ++c) { 7432 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7433 switch(coneSize) { 7434 case 3: 7435 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7436 break; 7437 case 4: 7438 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7439 break; 7440 default: 7441 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7442 } 7443 if (cell >= 0) break; 7444 } 7445 break; 7446 case 3: 7447 for(c = cStart; c < cEnd; ++c) { 7448 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7449 switch(coneSize) { 7450 case 4: 7451 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 7452 break; 7453 case 8: 7454 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 7455 break; 7456 default: 7457 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7458 } 7459 if (cell >= 0) break; 7460 } 7461 break; 7462 default: 7463 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 7464 } 7465 cells[p] = cell; 7466 } 7467 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 7468 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 7469 PetscFunctionReturn(0); 7470 } 7471 7472 /******************************** FEM Support **********************************/ 7473 7474 #undef __FUNCT__ 7475 #define __FUNCT__ "DMPlexVecGetClosure" 7476 /*@C 7477 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 7478 7479 Not collective 7480 7481 Input Parameters: 7482 + dm - The DM 7483 . section - The section describing the layout in v, or PETSC_NULL to use the default section 7484 . v - The local vector 7485 - point - The sieve point in the DM 7486 7487 Output Parameters: 7488 + csize - The number of values in the closure, or PETSC_NULL 7489 - values - The array of values, which is a borrowed array and should not be freed 7490 7491 Level: intermediate 7492 7493 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7494 @*/ 7495 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 7496 PetscScalar *array, *vArray; 7497 PetscInt *points = PETSC_NULL; 7498 PetscInt offsets[32]; 7499 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 7500 PetscErrorCode ierr; 7501 7502 PetscFunctionBegin; 7503 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7504 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7505 if (!section) { 7506 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7507 } 7508 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7509 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7510 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7511 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7512 /* Compress out points not in the section */ 7513 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7514 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7515 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7516 points[q*2] = points[p]; 7517 points[q*2+1] = points[p+1]; 7518 ++q; 7519 } 7520 } 7521 numPoints = q; 7522 for (p = 0, size = 0; p < numPoints*2; p += 2) { 7523 PetscInt dof, fdof; 7524 7525 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7526 for (f = 0; f < numFields; ++f) { 7527 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7528 offsets[f+1] += fdof; 7529 } 7530 size += dof; 7531 } 7532 for (f = 1; f < numFields; ++f) { 7533 offsets[f+1] += offsets[f]; 7534 } 7535 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 7536 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 7537 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 7538 for (p = 0; p < numPoints*2; p += 2) { 7539 PetscInt o = points[p+1]; 7540 PetscInt dof, off, d; 7541 PetscScalar *varr; 7542 7543 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7544 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 7545 varr = &vArray[off]; 7546 if (numFields) { 7547 PetscInt fdof, foff, fcomp, f, c; 7548 7549 for (f = 0, foff = 0; f < numFields; ++f) { 7550 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7551 if (o >= 0) { 7552 for (d = 0; d < fdof; ++d, ++offsets[f]) { 7553 array[offsets[f]] = varr[foff+d]; 7554 } 7555 } else { 7556 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7557 for (d = fdof/fcomp-1; d >= 0; --d) { 7558 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 7559 array[offsets[f]] = varr[foff+d*fcomp+c]; 7560 } 7561 } 7562 } 7563 foff += fdof; 7564 } 7565 } else { 7566 if (o >= 0) { 7567 for (d = 0; d < dof; ++d, ++offsets[0]) { 7568 array[offsets[0]] = varr[d]; 7569 } 7570 } else { 7571 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 7572 array[offsets[0]] = varr[d]; 7573 } 7574 } 7575 } 7576 } 7577 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7578 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 7579 if (csize) *csize = size; 7580 *values = array; 7581 PetscFunctionReturn(0); 7582 } 7583 7584 #undef __FUNCT__ 7585 #define __FUNCT__ "DMPlexVecRestoreClosure" 7586 /*@C 7587 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 7588 7589 Not collective 7590 7591 Input Parameters: 7592 + dm - The DM 7593 . section - The section describing the layout in v, or PETSC_NULL to use the default section 7594 . v - The local vector 7595 . point - The sieve point in the DM 7596 . csize - The number of values in the closure, or PETSC_NULL 7597 - values - The array of values, which is a borrowed array and should not be freed 7598 7599 Level: intermediate 7600 7601 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7602 @*/ 7603 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 7604 PetscInt size = 0; 7605 PetscErrorCode ierr; 7606 7607 PetscFunctionBegin; 7608 /* Should work without recalculating size */ 7609 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 7610 PetscFunctionReturn(0); 7611 } 7612 7613 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 7614 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 7615 7616 #undef __FUNCT__ 7617 #define __FUNCT__ "updatePoint_private" 7618 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 7619 { 7620 PetscInt cdof; /* The number of constraints on this point */ 7621 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7622 PetscScalar *a; 7623 PetscInt off, cind = 0, k; 7624 PetscErrorCode ierr; 7625 7626 PetscFunctionBegin; 7627 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 7628 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 7629 a = &array[off]; 7630 if (!cdof || setBC) { 7631 if (orientation >= 0) { 7632 for (k = 0; k < dof; ++k) { 7633 fuse(&a[k], values[k]); 7634 } 7635 } else { 7636 for (k = 0; k < dof; ++k) { 7637 fuse(&a[k], values[dof-k-1]); 7638 } 7639 } 7640 } else { 7641 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 7642 if (orientation >= 0) { 7643 for (k = 0; k < dof; ++k) { 7644 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7645 fuse(&a[k], values[k]); 7646 } 7647 } else { 7648 for (k = 0; k < dof; ++k) { 7649 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7650 fuse(&a[k], values[dof-k-1]); 7651 } 7652 } 7653 } 7654 PetscFunctionReturn(0); 7655 } 7656 7657 #undef __FUNCT__ 7658 #define __FUNCT__ "updatePointFields_private" 7659 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) { 7660 PetscScalar *a; 7661 PetscInt numFields, off, foff, f; 7662 PetscErrorCode ierr; 7663 7664 PetscFunctionBegin; 7665 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7666 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 7667 a = &array[off]; 7668 for (f = 0, foff = 0; f < numFields; ++f) { 7669 PetscInt fdof, fcomp, fcdof; 7670 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 7671 PetscInt cind = 0, k, c; 7672 7673 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7674 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 7675 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 7676 if (!fcdof || setBC) { 7677 if (orientation >= 0) { 7678 for (k = 0; k < fdof; ++k) { 7679 fuse(&a[foff+k], values[foffs[f]+k]); 7680 } 7681 } else { 7682 for (k = fdof/fcomp-1; k >= 0; --k) { 7683 for (c = 0; c < fcomp; ++c) { 7684 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 7685 } 7686 } 7687 } 7688 } else { 7689 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 7690 if (orientation >= 0) { 7691 for (k = 0; k < fdof; ++k) { 7692 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 7693 fuse(&a[foff+k], values[foffs[f]+k]); 7694 } 7695 } else { 7696 for (k = fdof/fcomp-1; k >= 0; --k) { 7697 for (c = 0; c < fcomp; ++c) { 7698 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 7699 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 7700 } 7701 } 7702 } 7703 } 7704 foff += fdof; 7705 foffs[f] += fdof; 7706 } 7707 PetscFunctionReturn(0); 7708 } 7709 7710 #undef __FUNCT__ 7711 #define __FUNCT__ "DMPlexVecSetClosure" 7712 /*@C 7713 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 7714 7715 Not collective 7716 7717 Input Parameters: 7718 + dm - The DM 7719 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 7720 . v - The local vector 7721 . point - The sieve point in the DM 7722 . values - The array of values, which is a borrowed array and should not be freed 7723 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7724 7725 Level: intermediate 7726 7727 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 7728 @*/ 7729 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) { 7730 PetscScalar *array; 7731 PetscInt *points = PETSC_NULL; 7732 PetscInt offsets[32]; 7733 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 7734 PetscErrorCode ierr; 7735 7736 PetscFunctionBegin; 7737 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7738 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7739 if (!section) { 7740 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7741 } 7742 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7743 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7744 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7745 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7746 /* Compress out points not in the section */ 7747 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7748 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7749 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7750 points[q*2] = points[p]; 7751 points[q*2+1] = points[p+1]; 7752 ++q; 7753 } 7754 } 7755 numPoints = q; 7756 for (p = 0; p < numPoints*2; p += 2) { 7757 PetscInt fdof; 7758 7759 for (f = 0; f < numFields; ++f) { 7760 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7761 offsets[f+1] += fdof; 7762 } 7763 } 7764 for (f = 1; f < numFields; ++f) { 7765 offsets[f+1] += offsets[f]; 7766 } 7767 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 7768 if (numFields) { 7769 switch(mode) { 7770 case INSERT_VALUES: 7771 for (p = 0; p < numPoints*2; p += 2) { 7772 PetscInt o = points[p+1]; 7773 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 7774 } break; 7775 case INSERT_ALL_VALUES: 7776 for (p = 0; p < numPoints*2; p += 2) { 7777 PetscInt o = points[p+1]; 7778 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 7779 } break; 7780 case ADD_VALUES: 7781 for (p = 0; p < numPoints*2; p += 2) { 7782 PetscInt o = points[p+1]; 7783 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 7784 } break; 7785 case ADD_ALL_VALUES: 7786 for (p = 0; p < numPoints*2; p += 2) { 7787 PetscInt o = points[p+1]; 7788 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 7789 } break; 7790 default: 7791 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7792 } 7793 } else { 7794 switch(mode) { 7795 case INSERT_VALUES: 7796 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7797 PetscInt o = points[p+1]; 7798 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7799 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 7800 } break; 7801 case INSERT_ALL_VALUES: 7802 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7803 PetscInt o = points[p+1]; 7804 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7805 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 7806 } break; 7807 case ADD_VALUES: 7808 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7809 PetscInt o = points[p+1]; 7810 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7811 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 7812 } break; 7813 case ADD_ALL_VALUES: 7814 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7815 PetscInt o = points[p+1]; 7816 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7817 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 7818 } break; 7819 default: 7820 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7821 } 7822 } 7823 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7824 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 7825 PetscFunctionReturn(0); 7826 } 7827 7828 #undef __FUNCT__ 7829 #define __FUNCT__ "DMPlexPrintMatSetValues" 7830 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 7831 { 7832 PetscMPIInt rank; 7833 PetscInt i, j; 7834 PetscErrorCode ierr; 7835 7836 PetscFunctionBegin; 7837 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 7838 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 7839 for (i = 0; i < numIndices; i++) { 7840 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 7841 } 7842 for (i = 0; i < numIndices; i++) { 7843 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 7844 for (j = 0; j < numIndices; j++) { 7845 #ifdef PETSC_USE_COMPLEX 7846 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 7847 #else 7848 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 7849 #endif 7850 } 7851 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 7852 } 7853 PetscFunctionReturn(0); 7854 } 7855 7856 #undef __FUNCT__ 7857 #define __FUNCT__ "indicesPoint_private" 7858 /* . off - The global offset of this point */ 7859 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 7860 PetscInt cdof; /* The number of constraints on this point */ 7861 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7862 PetscInt cind = 0, k; 7863 PetscErrorCode ierr; 7864 7865 PetscFunctionBegin; 7866 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 7867 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 7868 if (!cdof || setBC) { 7869 if (orientation >= 0) { 7870 for (k = 0; k < dof; ++k) { 7871 indices[k] = off+k; 7872 } 7873 } else { 7874 for (k = 0; k < dof; ++k) { 7875 indices[dof-k-1] = off+k; 7876 } 7877 } 7878 } else { 7879 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 7880 if (orientation >= 0) { 7881 for (k = 0; k < dof; ++k) { 7882 if ((cind < cdof) && (k == cdofs[cind])) { 7883 /* Insert check for returning constrained indices */ 7884 indices[k] = -(off+k+1); 7885 ++cind; 7886 } else { 7887 indices[k] = off+k-cind; 7888 } 7889 } 7890 } else { 7891 for (k = 0; k < dof; ++k) { 7892 if ((cind < cdof) && (k == cdofs[cind])) { 7893 /* Insert check for returning constrained indices */ 7894 indices[dof-k-1] = -(off+k+1); 7895 ++cind; 7896 } else { 7897 indices[dof-k-1] = off+k-cind; 7898 } 7899 } 7900 } 7901 } 7902 PetscFunctionReturn(0); 7903 } 7904 7905 #undef __FUNCT__ 7906 #define __FUNCT__ "indicesPointFields_private" 7907 /* . off - The global offset of this point */ 7908 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 7909 PetscInt numFields, foff, f; 7910 PetscErrorCode ierr; 7911 7912 PetscFunctionBegin; 7913 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7914 for (f = 0, foff = 0; f < numFields; ++f) { 7915 PetscInt fdof, fcomp, cfdof; 7916 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 7917 PetscInt cind = 0, k, c; 7918 7919 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7920 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 7921 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 7922 if (!cfdof || setBC) { 7923 if (orientation >= 0) { 7924 for (k = 0; k < fdof; ++k) { 7925 indices[foffs[f]+k] = off+foff+k; 7926 } 7927 } else { 7928 for (k = fdof/fcomp-1; k >= 0; --k) { 7929 for (c = 0; c < fcomp; ++c) { 7930 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 7931 } 7932 } 7933 } 7934 } else { 7935 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 7936 if (orientation >= 0) { 7937 for (k = 0; k < fdof; ++k) { 7938 if ((cind < cfdof) && (k == fcdofs[cind])) { 7939 indices[foffs[f]+k] = -(off+foff+k+1); 7940 ++cind; 7941 } else { 7942 indices[foffs[f]+k] = off+foff+k-cind; 7943 } 7944 } 7945 } else { 7946 for (k = fdof/fcomp-1; k >= 0; --k) { 7947 for (c = 0; c < fcomp; ++c) { 7948 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 7949 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 7950 ++cind; 7951 } else { 7952 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 7953 } 7954 } 7955 } 7956 } 7957 } 7958 foff += fdof - cfdof; 7959 foffs[f] += fdof; 7960 } 7961 PetscFunctionReturn(0); 7962 } 7963 7964 #undef __FUNCT__ 7965 #define __FUNCT__ "DMPlexMatSetClosure" 7966 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 7967 { 7968 DM_Plex *mesh = (DM_Plex *) dm->data; 7969 PetscInt *points = PETSC_NULL; 7970 PetscInt *indices; 7971 PetscInt offsets[32]; 7972 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 7973 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 7974 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 7975 PetscErrorCode ierr; 7976 7977 PetscFunctionBegin; 7978 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7979 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 7980 if (useDefault) { 7981 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7982 } 7983 if (useGlobalDefault) { 7984 if (useDefault) { 7985 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 7986 } else { 7987 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7988 } 7989 } 7990 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7991 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7992 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7993 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7994 /* Compress out points not in the section */ 7995 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7996 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7997 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7998 points[q*2] = points[p]; 7999 points[q*2+1] = points[p+1]; 8000 ++q; 8001 } 8002 } 8003 numPoints = q; 8004 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8005 PetscInt fdof; 8006 8007 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8008 for (f = 0; f < numFields; ++f) { 8009 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8010 offsets[f+1] += fdof; 8011 } 8012 numIndices += dof; 8013 } 8014 for (f = 1; f < numFields; ++f) { 8015 offsets[f+1] += offsets[f]; 8016 } 8017 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8018 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8019 if (numFields) { 8020 for (p = 0; p < numPoints*2; p += 2) { 8021 PetscInt o = points[p+1]; 8022 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8023 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8024 } 8025 } else { 8026 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8027 PetscInt o = points[p+1]; 8028 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8029 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8030 } 8031 } 8032 if (useGlobalDefault && !useDefault) { 8033 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8034 } 8035 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8036 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8037 if (ierr) { 8038 PetscMPIInt rank; 8039 PetscErrorCode ierr2; 8040 8041 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8042 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8043 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8044 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8045 CHKERRQ(ierr); 8046 } 8047 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8048 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8049 PetscFunctionReturn(0); 8050 } 8051 8052 #undef __FUNCT__ 8053 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8054 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8055 { 8056 PetscSection coordSection; 8057 Vec coordinates; 8058 const PetscScalar *coords; 8059 const PetscInt dim = 2; 8060 PetscInt d, f; 8061 PetscErrorCode ierr; 8062 8063 PetscFunctionBegin; 8064 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8065 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8066 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8067 if (v0) { 8068 for (d = 0; d < dim; d++) { 8069 v0[d] = PetscRealPart(coords[d]); 8070 } 8071 } 8072 if (J) { 8073 for (d = 0; d < dim; d++) { 8074 for (f = 0; f < dim; f++) { 8075 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8076 } 8077 } 8078 *detJ = J[0]*J[3] - J[1]*J[2]; 8079 #if 0 8080 if (detJ < 0.0) { 8081 const PetscReal xLength = mesh->periodicity[0]; 8082 8083 if (xLength != 0.0) { 8084 PetscReal v0x = coords[0*dim+0]; 8085 8086 if (v0x == 0.0) { 8087 v0x = v0[0] = xLength; 8088 } 8089 for (f = 0; f < dim; f++) { 8090 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8091 8092 J[0*dim+f] = 0.5*(px - v0x); 8093 } 8094 } 8095 detJ = J[0]*J[3] - J[1]*J[2]; 8096 } 8097 #endif 8098 PetscLogFlops(8.0 + 3.0); 8099 } 8100 if (invJ) { 8101 const PetscReal invDet = 1.0/(*detJ); 8102 8103 invJ[0] = invDet*J[3]; 8104 invJ[1] = -invDet*J[1]; 8105 invJ[2] = -invDet*J[2]; 8106 invJ[3] = invDet*J[0]; 8107 PetscLogFlops(5.0); 8108 } 8109 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8110 PetscFunctionReturn(0); 8111 } 8112 8113 #undef __FUNCT__ 8114 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8115 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8116 { 8117 PetscSection coordSection; 8118 Vec coordinates; 8119 const PetscScalar *coords; 8120 const PetscInt dim = 2; 8121 PetscInt d, f; 8122 PetscErrorCode ierr; 8123 8124 PetscFunctionBegin; 8125 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8126 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8127 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8128 if (v0) { 8129 for (d = 0; d < dim; d++) { 8130 v0[d] = PetscRealPart(coords[d]); 8131 } 8132 } 8133 if (J) { 8134 for (d = 0; d < dim; d++) { 8135 for (f = 0; f < dim; f++) { 8136 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8137 } 8138 } 8139 *detJ = J[0]*J[3] - J[1]*J[2]; 8140 PetscLogFlops(8.0 + 3.0); 8141 } 8142 if (invJ) { 8143 const PetscReal invDet = 1.0/(*detJ); 8144 8145 invJ[0] = invDet*J[3]; 8146 invJ[1] = -invDet*J[1]; 8147 invJ[2] = -invDet*J[2]; 8148 invJ[3] = invDet*J[0]; 8149 PetscLogFlops(5.0); 8150 } 8151 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8152 PetscFunctionReturn(0); 8153 } 8154 8155 #undef __FUNCT__ 8156 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8157 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8158 { 8159 PetscSection coordSection; 8160 Vec coordinates; 8161 const PetscScalar *coords; 8162 const PetscInt dim = 3; 8163 PetscInt d, f; 8164 PetscErrorCode ierr; 8165 8166 PetscFunctionBegin; 8167 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8168 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8169 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8170 if (v0) { 8171 for (d = 0; d < dim; d++) { 8172 v0[d] = PetscRealPart(coords[d]); 8173 } 8174 } 8175 if (J) { 8176 for (d = 0; d < dim; d++) { 8177 for (f = 0; f < dim; f++) { 8178 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8179 } 8180 } 8181 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8182 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8183 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8184 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8185 PetscLogFlops(18.0 + 12.0); 8186 } 8187 if (invJ) { 8188 const PetscReal invDet = -1.0/(*detJ); 8189 8190 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8191 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8192 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8193 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8194 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8195 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8196 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8197 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8198 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8199 PetscLogFlops(37.0); 8200 } 8201 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8202 PetscFunctionReturn(0); 8203 } 8204 8205 #undef __FUNCT__ 8206 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8207 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8208 { 8209 PetscSection coordSection; 8210 Vec coordinates; 8211 const PetscScalar *coords; 8212 const PetscInt dim = 3; 8213 PetscInt d; 8214 PetscErrorCode ierr; 8215 8216 PetscFunctionBegin; 8217 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8218 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8219 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8220 if (v0) { 8221 for (d = 0; d < dim; d++) { 8222 v0[d] = PetscRealPart(coords[d]); 8223 } 8224 } 8225 if (J) { 8226 for (d = 0; d < dim; d++) { 8227 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8228 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8229 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8230 } 8231 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8232 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8233 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8234 PetscLogFlops(18.0 + 12.0); 8235 } 8236 if (invJ) { 8237 const PetscReal invDet = -1.0/(*detJ); 8238 8239 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8240 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8241 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8242 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8243 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8244 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8245 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8246 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8247 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8248 PetscLogFlops(37.0); 8249 } 8250 *detJ *= 8.0; 8251 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8252 PetscFunctionReturn(0); 8253 } 8254 8255 #undef __FUNCT__ 8256 #define __FUNCT__ "DMPlexComputeCellGeometry" 8257 /*@C 8258 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8259 8260 Collective on DM 8261 8262 Input Arguments: 8263 + dm - the DM 8264 - cell - the cell 8265 8266 Output Arguments: 8267 + v0 - the translation part of this affine transform 8268 . J - the Jacobian of the transform to the reference element 8269 . invJ - the inverse of the Jacobian 8270 - detJ - the Jacobian determinant 8271 8272 Level: advanced 8273 8274 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8275 @*/ 8276 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) { 8277 PetscInt dim, maxConeSize; 8278 PetscErrorCode ierr; 8279 8280 PetscFunctionBegin; 8281 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8282 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 8283 switch(dim) { 8284 case 2: 8285 switch(maxConeSize) { 8286 case 3: 8287 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8288 break; 8289 case 4: 8290 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8291 break; 8292 default: 8293 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize); 8294 } 8295 break; 8296 case 3: 8297 switch(maxConeSize) { 8298 case 4: 8299 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8300 break; 8301 case 8: 8302 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8303 break; 8304 default: 8305 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize); 8306 } 8307 break; 8308 default: 8309 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8310 } 8311 PetscFunctionReturn(0); 8312 } 8313 8314 #undef __FUNCT__ 8315 #define __FUNCT__ "DMPlexGetFaceOrientation" 8316 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) { 8317 MPI_Comm comm = ((PetscObject) dm)->comm; 8318 PetscBool posOrient = PETSC_FALSE; 8319 const PetscInt debug = 0; 8320 PetscInt cellDim, faceSize, f; 8321 PetscErrorCode ierr; 8322 8323 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 8324 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 8325 8326 if (cellDim == numCorners-1) { 8327 /* Simplices */ 8328 faceSize = numCorners-1; 8329 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 8330 } else if (cellDim == 1 && numCorners == 3) { 8331 /* Quadratic line */ 8332 faceSize = 1; 8333 posOrient = PETSC_TRUE; 8334 } else if (cellDim == 2 && numCorners == 4) { 8335 /* Quads */ 8336 faceSize = 2; 8337 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 8338 posOrient = PETSC_TRUE; 8339 } else if ((indices[0] == 3) && (indices[1] == 0)) { 8340 posOrient = PETSC_TRUE; 8341 } else { 8342 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 8343 posOrient = PETSC_FALSE; 8344 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 8345 } 8346 } else if (cellDim == 2 && numCorners == 6) { 8347 /* Quadratic triangle (I hate this) */ 8348 /* Edges are determined by the first 2 vertices (corners of edges) */ 8349 const PetscInt faceSizeTri = 3; 8350 PetscInt sortedIndices[3], i, iFace; 8351 PetscBool found = PETSC_FALSE; 8352 PetscInt faceVerticesTriSorted[9] = { 8353 0, 3, 4, /* bottom */ 8354 1, 4, 5, /* right */ 8355 2, 3, 5, /* left */ 8356 }; 8357 PetscInt faceVerticesTri[9] = { 8358 0, 3, 4, /* bottom */ 8359 1, 4, 5, /* right */ 8360 2, 5, 3, /* left */ 8361 }; 8362 8363 faceSize = faceSizeTri; 8364 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 8365 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 8366 for (iFace = 0; iFace < 3; ++iFace) { 8367 const PetscInt ii = iFace*faceSizeTri; 8368 PetscInt fVertex, cVertex; 8369 8370 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 8371 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 8372 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 8373 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 8374 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 8375 faceVertices[fVertex] = origVertices[cVertex]; 8376 break; 8377 } 8378 } 8379 } 8380 found = PETSC_TRUE; 8381 break; 8382 } 8383 } 8384 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 8385 if (posOriented) {*posOriented = PETSC_TRUE;} 8386 PetscFunctionReturn(0); 8387 } else if (cellDim == 2 && numCorners == 9) { 8388 /* Quadratic quad (I hate this) */ 8389 /* Edges are determined by the first 2 vertices (corners of edges) */ 8390 const PetscInt faceSizeQuad = 3; 8391 PetscInt sortedIndices[3], i, iFace; 8392 PetscBool found = PETSC_FALSE; 8393 PetscInt faceVerticesQuadSorted[12] = { 8394 0, 1, 4, /* bottom */ 8395 1, 2, 5, /* right */ 8396 2, 3, 6, /* top */ 8397 0, 3, 7, /* left */ 8398 }; 8399 PetscInt faceVerticesQuad[12] = { 8400 0, 1, 4, /* bottom */ 8401 1, 2, 5, /* right */ 8402 2, 3, 6, /* top */ 8403 3, 0, 7, /* left */ 8404 }; 8405 8406 faceSize = faceSizeQuad; 8407 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 8408 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 8409 for (iFace = 0; iFace < 4; ++iFace) { 8410 const PetscInt ii = iFace*faceSizeQuad; 8411 PetscInt fVertex, cVertex; 8412 8413 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 8414 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 8415 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 8416 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 8417 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 8418 faceVertices[fVertex] = origVertices[cVertex]; 8419 break; 8420 } 8421 } 8422 } 8423 found = PETSC_TRUE; 8424 break; 8425 } 8426 } 8427 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 8428 if (posOriented) {*posOriented = PETSC_TRUE;} 8429 PetscFunctionReturn(0); 8430 } else if (cellDim == 3 && numCorners == 8) { 8431 /* Hexes 8432 A hex is two oriented quads with the normal of the first 8433 pointing up at the second. 8434 8435 7---6 8436 /| /| 8437 4---5 | 8438 | 3-|-2 8439 |/ |/ 8440 0---1 8441 8442 Faces are determined by the first 4 vertices (corners of faces) */ 8443 const PetscInt faceSizeHex = 4; 8444 PetscInt sortedIndices[4], i, iFace; 8445 PetscBool found = PETSC_FALSE; 8446 PetscInt faceVerticesHexSorted[24] = { 8447 0, 1, 2, 3, /* bottom */ 8448 4, 5, 6, 7, /* top */ 8449 0, 1, 4, 5, /* front */ 8450 1, 2, 5, 6, /* right */ 8451 2, 3, 6, 7, /* back */ 8452 0, 3, 4, 7, /* left */ 8453 }; 8454 PetscInt faceVerticesHex[24] = { 8455 3, 2, 1, 0, /* bottom */ 8456 4, 5, 6, 7, /* top */ 8457 0, 1, 5, 4, /* front */ 8458 1, 2, 6, 5, /* right */ 8459 2, 3, 7, 6, /* back */ 8460 3, 0, 4, 7, /* left */ 8461 }; 8462 8463 faceSize = faceSizeHex; 8464 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 8465 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 8466 for (iFace = 0; iFace < 6; ++iFace) { 8467 const PetscInt ii = iFace*faceSizeHex; 8468 PetscInt fVertex, cVertex; 8469 8470 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 8471 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 8472 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 8473 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 8474 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 8475 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 8476 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 8477 faceVertices[fVertex] = origVertices[cVertex]; 8478 break; 8479 } 8480 } 8481 } 8482 found = PETSC_TRUE; 8483 break; 8484 } 8485 } 8486 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 8487 if (posOriented) {*posOriented = PETSC_TRUE;} 8488 PetscFunctionReturn(0); 8489 } else if (cellDim == 3 && numCorners == 10) { 8490 /* Quadratic tet */ 8491 /* Faces are determined by the first 3 vertices (corners of faces) */ 8492 const PetscInt faceSizeTet = 6; 8493 PetscInt sortedIndices[6], i, iFace; 8494 PetscBool found = PETSC_FALSE; 8495 PetscInt faceVerticesTetSorted[24] = { 8496 0, 1, 2, 6, 7, 8, /* bottom */ 8497 0, 3, 4, 6, 7, 9, /* front */ 8498 1, 4, 5, 7, 8, 9, /* right */ 8499 2, 3, 5, 6, 8, 9, /* left */ 8500 }; 8501 PetscInt faceVerticesTet[24] = { 8502 0, 1, 2, 6, 7, 8, /* bottom */ 8503 0, 4, 3, 6, 7, 9, /* front */ 8504 1, 5, 4, 7, 8, 9, /* right */ 8505 2, 3, 5, 8, 6, 9, /* left */ 8506 }; 8507 8508 faceSize = faceSizeTet; 8509 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 8510 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 8511 for (iFace=0; iFace < 4; ++iFace) { 8512 const PetscInt ii = iFace*faceSizeTet; 8513 PetscInt fVertex, cVertex; 8514 8515 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 8516 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 8517 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 8518 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 8519 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 8520 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 8521 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 8522 faceVertices[fVertex] = origVertices[cVertex]; 8523 break; 8524 } 8525 } 8526 } 8527 found = PETSC_TRUE; 8528 break; 8529 } 8530 } 8531 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 8532 if (posOriented) {*posOriented = PETSC_TRUE;} 8533 PetscFunctionReturn(0); 8534 } else if (cellDim == 3 && numCorners == 27) { 8535 /* Quadratic hexes (I hate this) 8536 A hex is two oriented quads with the normal of the first 8537 pointing up at the second. 8538 8539 7---6 8540 /| /| 8541 4---5 | 8542 | 3-|-2 8543 |/ |/ 8544 0---1 8545 8546 Faces are determined by the first 4 vertices (corners of faces) */ 8547 const PetscInt faceSizeQuadHex = 9; 8548 PetscInt sortedIndices[9], i, iFace; 8549 PetscBool found = PETSC_FALSE; 8550 PetscInt faceVerticesQuadHexSorted[54] = { 8551 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 8552 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 8553 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 8554 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 8555 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 8556 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 8557 }; 8558 PetscInt faceVerticesQuadHex[54] = { 8559 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 8560 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 8561 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 8562 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 8563 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 8564 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 8565 }; 8566 8567 faceSize = faceSizeQuadHex; 8568 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 8569 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 8570 for (iFace = 0; iFace < 6; ++iFace) { 8571 const PetscInt ii = iFace*faceSizeQuadHex; 8572 PetscInt fVertex, cVertex; 8573 8574 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 8575 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 8576 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 8577 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 8578 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 8579 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 8580 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 8581 faceVertices[fVertex] = origVertices[cVertex]; 8582 break; 8583 } 8584 } 8585 } 8586 found = PETSC_TRUE; 8587 break; 8588 } 8589 } 8590 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 8591 if (posOriented) {*posOriented = PETSC_TRUE;} 8592 PetscFunctionReturn(0); 8593 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 8594 if (!posOrient) { 8595 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 8596 for (f = 0; f < faceSize; ++f) { 8597 faceVertices[f] = origVertices[faceSize-1 - f]; 8598 } 8599 } else { 8600 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 8601 for (f = 0; f < faceSize; ++f) { 8602 faceVertices[f] = origVertices[f]; 8603 } 8604 } 8605 if (posOriented) {*posOriented = posOrient;} 8606 PetscFunctionReturn(0); 8607 } 8608 8609 #undef __FUNCT__ 8610 #define __FUNCT__ "DMPlexGetOrientedFace" 8611 /* 8612 Given a cell and a face, as a set of vertices, 8613 return the oriented face, as a set of vertices, in faceVertices 8614 The orientation is such that the face normal points out of the cell 8615 */ 8616 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 8617 { 8618 const PetscInt *cone = PETSC_NULL; 8619 PetscInt coneSize, v, f, v2; 8620 PetscInt oppositeVertex = -1; 8621 PetscErrorCode ierr; 8622 8623 PetscFunctionBegin; 8624 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8625 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 8626 for (v = 0, v2 = 0; v < coneSize; ++v) { 8627 PetscBool found = PETSC_FALSE; 8628 8629 for (f = 0; f < faceSize; ++f) { 8630 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 8631 } 8632 if (found) { 8633 indices[v2] = v; 8634 origVertices[v2] = cone[v]; 8635 ++v2; 8636 } else { 8637 oppositeVertex = v; 8638 } 8639 } 8640 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 8641 PetscFunctionReturn(0); 8642 } 8643 8644 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8645 { 8646 switch(i) { 8647 case 0: 8648 switch(j) { 8649 case 0: return 0; 8650 case 1: 8651 switch(k) { 8652 case 0: return 0; 8653 case 1: return 0; 8654 case 2: return 1; 8655 } 8656 case 2: 8657 switch(k) { 8658 case 0: return 0; 8659 case 1: return -1; 8660 case 2: return 0; 8661 } 8662 } 8663 case 1: 8664 switch(j) { 8665 case 0: 8666 switch(k) { 8667 case 0: return 0; 8668 case 1: return 0; 8669 case 2: return -1; 8670 } 8671 case 1: return 0; 8672 case 2: 8673 switch(k) { 8674 case 0: return 1; 8675 case 1: return 0; 8676 case 2: return 0; 8677 } 8678 } 8679 case 2: 8680 switch(j) { 8681 case 0: 8682 switch(k) { 8683 case 0: return 0; 8684 case 1: return 1; 8685 case 2: return 0; 8686 } 8687 case 1: 8688 switch(k) { 8689 case 0: return -1; 8690 case 1: return 0; 8691 case 2: return 0; 8692 } 8693 case 2: return 0; 8694 } 8695 } 8696 return 0; 8697 } 8698 8699 #undef __FUNCT__ 8700 #define __FUNCT__ "DMPlexCreateRigidBody" 8701 /*@C 8702 DMPlexCreateRigidBody - create rigid body modes from coordinates 8703 8704 Collective on DM 8705 8706 Input Arguments: 8707 + dm - the DM 8708 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 8709 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 8710 8711 Output Argument: 8712 . sp - the null space 8713 8714 Note: This is necessary to take account of Dirichlet conditions on the displacements 8715 8716 Level: advanced 8717 8718 .seealso: MatNullSpaceCreate() 8719 @*/ 8720 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8721 { 8722 MPI_Comm comm = ((PetscObject) dm)->comm; 8723 Vec coordinates, localMode, mode[6]; 8724 PetscSection coordSection; 8725 PetscScalar *coords; 8726 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8727 PetscErrorCode ierr; 8728 8729 PetscFunctionBegin; 8730 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8731 if (dim == 1) { 8732 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 8733 PetscFunctionReturn(0); 8734 } 8735 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8736 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8737 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8738 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8739 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8740 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8741 m = (dim*(dim+1))/2; 8742 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8743 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8744 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8745 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8746 /* Assume P1 */ 8747 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8748 for (d = 0; d < dim; ++d) { 8749 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8750 8751 values[d] = 1.0; 8752 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8753 for (v = vStart; v < vEnd; ++v) { 8754 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8755 } 8756 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8757 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8758 } 8759 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8760 for (d = dim; d < dim*(dim+1)/2; ++d) { 8761 PetscInt i, j, k = dim > 2 ? d - dim : d; 8762 8763 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8764 for (v = vStart; v < vEnd; ++v) { 8765 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8766 PetscInt off; 8767 8768 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8769 for (i = 0; i < dim; ++i) { 8770 for (j = 0; j < dim; ++j) { 8771 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8772 } 8773 } 8774 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8775 } 8776 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8777 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8778 } 8779 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8780 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8781 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 8782 /* Orthonormalize system */ 8783 for (i = dim; i < m; ++i) { 8784 PetscScalar dots[6]; 8785 8786 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8787 for (j = 0; j < i; ++j) dots[j] *= -1.0; 8788 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8789 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 8790 } 8791 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 8792 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 8793 PetscFunctionReturn(0); 8794 } 8795 8796 #undef __FUNCT__ 8797 #define __FUNCT__ "DMPlexGetVTKBounds" 8798 PetscErrorCode DMPlexGetVTKBounds(DM dm, PetscInt *cMax, PetscInt *vMax) 8799 { 8800 DM_Plex *mesh = (DM_Plex *) dm->data; 8801 8802 PetscFunctionBegin; 8803 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8804 if (cMax) *cMax = mesh->vtkCellMax; 8805 if (vMax) *vMax = mesh->vtkVertexMax; 8806 PetscFunctionReturn(0); 8807 } 8808 8809 #undef __FUNCT__ 8810 #define __FUNCT__ "DMPlexSetVTKBounds" 8811 PetscErrorCode DMPlexSetVTKBounds(DM dm, PetscInt cMax, PetscInt vMax) 8812 { 8813 DM_Plex *mesh = (DM_Plex *) dm->data; 8814 8815 PetscFunctionBegin; 8816 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8817 if (cMax >= 0) mesh->vtkCellMax = cMax; 8818 if (vMax >= 0) mesh->vtkVertexMax = vMax; 8819 PetscFunctionReturn(0); 8820 } 8821 8822 #undef __FUNCT__ 8823 #define __FUNCT__ "DMPlexGetVTKCellHeight" 8824 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8825 { 8826 DM_Plex *mesh = (DM_Plex *) dm->data; 8827 8828 PetscFunctionBegin; 8829 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8830 PetscValidPointer(cellHeight, 2); 8831 *cellHeight = mesh->vtkCellHeight; 8832 PetscFunctionReturn(0); 8833 } 8834 8835 #undef __FUNCT__ 8836 #define __FUNCT__ "DMPlexSetVTKCellHeight" 8837 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8838 { 8839 DM_Plex *mesh = (DM_Plex *) dm->data; 8840 8841 PetscFunctionBegin; 8842 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8843 mesh->vtkCellHeight = cellHeight; 8844 PetscFunctionReturn(0); 8845 } 8846 8847 #undef __FUNCT__ 8848 #define __FUNCT__ "DMPlexInsertFace_Private" 8849 /* 8850 DMPlexInsertFace_Private - Puts a face into the mesh 8851 8852 Not collective 8853 8854 Input Parameters: 8855 + dm - The DMPlex 8856 . numFaceVertex - The number of vertices in the face 8857 . faceVertices - The vertices in the face for dm 8858 . subfaceVertices - The vertices in the face for subdm 8859 . numCorners - The number of vertices in the cell 8860 . cell - A cell in dm containing the face 8861 . subcell - A cell in subdm containing the face 8862 . firstFace - First face in the mesh 8863 - newFacePoint - Next face in the mesh 8864 8865 Output Parameters: 8866 . newFacePoint - Contains next face point number on input, updated on output 8867 8868 Level: developer 8869 */ 8870 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) 8871 { 8872 MPI_Comm comm = ((PetscObject) dm)->comm; 8873 DM_Plex *submesh = (DM_Plex *) subdm->data; 8874 const PetscInt *faces; 8875 PetscInt numFaces, coneSize; 8876 PetscErrorCode ierr; 8877 8878 PetscFunctionBegin; 8879 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 8880 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 8881 #if 0 8882 /* Cannot use this because support() has not been constructed yet */ 8883 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 8884 #else 8885 { 8886 PetscInt f; 8887 8888 numFaces = 0; 8889 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 8890 for(f = firstFace; f < *newFacePoint; ++f) { 8891 PetscInt dof, off, d; 8892 8893 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 8894 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 8895 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 8896 for(d = 0; d < dof; ++d) { 8897 const PetscInt p = submesh->cones[off+d]; 8898 PetscInt v; 8899 8900 for(v = 0; v < numFaceVertices; ++v) { 8901 if (subfaceVertices[v] == p) break; 8902 } 8903 if (v == numFaceVertices) break; 8904 } 8905 if (d == dof) { 8906 numFaces = 1; 8907 ((PetscInt *) faces)[0] = f; 8908 } 8909 } 8910 } 8911 #endif 8912 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 8913 else if (numFaces == 1) { 8914 /* Add the other cell neighbor for this face */ 8915 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 8916 } else { 8917 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 8918 PetscBool posOriented; 8919 8920 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 8921 origVertices = &orientedVertices[numFaceVertices]; 8922 indices = &orientedVertices[numFaceVertices*2]; 8923 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 8924 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 8925 /* TODO: I know that routine should return a permutation, not the indices */ 8926 for(v = 0; v < numFaceVertices; ++v) { 8927 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 8928 for(ov = 0; ov < numFaceVertices; ++ov) { 8929 if (orientedVertices[ov] == vertex) { 8930 orientedSubVertices[ov] = subvertex; 8931 break; 8932 } 8933 } 8934 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 8935 } 8936 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 8937 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 8938 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 8939 ++(*newFacePoint); 8940 } 8941 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 8942 PetscFunctionReturn(0); 8943 } 8944 8945 #undef __FUNCT__ 8946 #define __FUNCT__ "DMPlexCreateSubmesh" 8947 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 8948 { 8949 MPI_Comm comm = ((PetscObject) dm)->comm; 8950 DM_Plex *submesh; 8951 PetscBool boundaryFaces = PETSC_FALSE; 8952 PetscSection coordSection, subCoordSection; 8953 Vec coordinates, subCoordinates; 8954 PetscScalar *coords, *subCoords; 8955 IS labelIS; 8956 const PetscInt *subVertices; 8957 PetscInt *subVerticesActive, *tmpPoints; 8958 PetscInt *subCells = PETSC_NULL; 8959 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 8960 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 8961 PetscInt dim; /* Right now, do not specify dimension */ 8962 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 8963 PetscErrorCode ierr; 8964 8965 PetscFunctionBegin; 8966 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8967 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8968 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8969 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 8970 ierr = DMPlexGetVTKBounds(dm, &cMax, &vMax);CHKERRQ(ierr); 8971 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 8972 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 8973 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 8974 subface = &face[maxConeSize]; 8975 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 8976 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 8977 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 8978 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 8979 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 8980 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 8981 maxSubCells = numSubVertices; 8982 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 8983 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 8984 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 8985 for(v = 0; v < numSubVertices; ++v) { 8986 const PetscInt vertex = subVertices[v]; 8987 PetscInt *star = PETSC_NULL; 8988 PetscInt starSize, numCells = 0; 8989 8990 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 8991 for(p = 0; p < starSize*2; p += 2) { 8992 const PetscInt point = star[p]; 8993 if ((point >= cStart) && (point < cEnd)) { 8994 star[numCells++] = point; 8995 } 8996 } 8997 numOldSubCells = numSubCells; 8998 for(c = 0; c < numCells; ++c) { 8999 const PetscInt cell = star[c]; 9000 PetscInt *closure = PETSC_NULL; 9001 PetscInt closureSize, numCorners = 0, faceSize = 0; 9002 PetscInt cellLoc; 9003 9004 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 9005 if (cellLoc >= 0) continue; 9006 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9007 for(p = 0; p < closureSize*2; p += 2) { 9008 const PetscInt point = closure[p]; 9009 if ((point >= vStart) && (point < vEnd)) { 9010 closure[numCorners++] = point; 9011 } 9012 } 9013 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 9014 for(corner = 0; corner < numCorners; ++corner) { 9015 const PetscInt cellVertex = closure[corner]; 9016 PetscInt subVertex; 9017 9018 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 9019 if (subVertex >= 0) { /* contains submesh vertex */ 9020 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9021 if (i == faceSize) { 9022 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 9023 face[faceSize] = cellVertex; 9024 subface[faceSize] = subVertex; 9025 ++faceSize; 9026 } 9027 } 9028 } 9029 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9030 if (faceSize >= nFV) { 9031 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9032 if (numSubCells >= maxSubCells) { 9033 PetscInt *tmpCells; 9034 maxSubCells *= 2; 9035 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 9036 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 9037 ierr = PetscFree(subCells);CHKERRQ(ierr); 9038 subCells = tmpCells; 9039 } 9040 /* TOOD: Maybe overestimate then squeeze out empty faces */ 9041 if (faceSize > nFV) { 9042 /* TODO: This is tricky. Maybe just add all faces */ 9043 numSubFaces++; 9044 } else { 9045 numSubFaces++; 9046 } 9047 for(f = 0; f < faceSize; ++f) { 9048 subVerticesActive[subface[f]] = 1; 9049 } 9050 subCells[numSubCells++] = cell; 9051 } 9052 } 9053 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9054 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 9055 } 9056 /* Pick out active subvertices */ 9057 for(v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 9058 if (subVerticesActive[v]) { 9059 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 9060 } 9061 } 9062 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 9063 /* Set cone sizes */ 9064 firstSubVertex = numSubCells; 9065 firstSubFace = numSubCells+numSubVerticesActive; 9066 newFacePoint = firstSubFace; 9067 for(c = 0; c < numSubCells; ++c) { 9068 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 9069 } 9070 for(f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 9071 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 9072 } 9073 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 9074 /* Create face cones */ 9075 for(c = 0; c < numSubCells; ++c) { 9076 const PetscInt cell = subCells[c]; 9077 PetscInt *closure = PETSC_NULL; 9078 PetscInt closureSize, numCorners = 0, faceSize = 0; 9079 9080 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9081 for(p = 0; p < closureSize*2; p += 2) { 9082 const PetscInt point = closure[p]; 9083 if ((point >= vStart) && (point < vEnd)) { 9084 closure[numCorners++] = point; 9085 } 9086 } 9087 for(corner = 0; corner < numCorners; ++corner) { 9088 const PetscInt cellVertex = closure[corner]; 9089 PetscInt subVertex; 9090 9091 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 9092 if (subVertex >= 0) { /* contains submesh vertex */ 9093 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9094 if (i == faceSize) { 9095 face[faceSize] = cellVertex; 9096 subface[faceSize] = numSubCells+subVertex; 9097 ++faceSize; 9098 } 9099 } 9100 } 9101 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9102 if (faceSize >= nFV) { 9103 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9104 // Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) 9105 // We have to take all the faces, and discard those in the interior 9106 // We check the join of the face vertices, which produces 2 cells if in the interior 9107 #if 0 9108 // This object just calls insert on each face that comes from subsets() 9109 // In fact, we can just always acll subsets(), since when we pass a single face it is a single call 9110 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 9111 PointArray faceVec(face->begin(), face->end()); 9112 9113 subsets(faceVec, nFV, inserter); 9114 #endif 9115 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 9116 } 9117 } 9118 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 9119 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 9120 /* Build coordinates */ 9121 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9122 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9123 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 9124 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 9125 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 9126 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 9127 } 9128 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 9129 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 9130 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 9131 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 9132 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 9133 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9134 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9135 for(v = 0; v < numSubVerticesActive; ++v) { 9136 const PetscInt vertex = subVerticesActive[v]; 9137 const PetscInt subVertex = firstSubVertex+v; 9138 PetscInt dof, off, sdof, soff; 9139 9140 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 9141 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 9142 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 9143 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 9144 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 9145 for(d = 0; d < dof; ++d) { 9146 subCoords[soff+d] = coords[off+d]; 9147 } 9148 } 9149 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9150 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9151 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 9152 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 9153 9154 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 9155 /* Create map from submesh points to original mesh points */ 9156 submesh = (DM_Plex *) (*subdm)->data; 9157 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 9158 for(c = 0; c < numSubCells; ++c) { 9159 tmpPoints[c] = subCells[c]; 9160 } 9161 for(v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 9162 tmpPoints[v] = subVerticesActive[v-numSubCells]; 9163 } 9164 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 9165 9166 ierr = PetscFree(subCells);CHKERRQ(ierr); 9167 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 9168 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 9169 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 9170 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9171 PetscFunctionReturn(0); 9172 } 9173 9174 #undef __FUNCT__ 9175 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9176 /* We can easily have a form that takes an IS instead */ 9177 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9178 { 9179 PetscSection section, globalSection; 9180 PetscInt *numbers, p; 9181 PetscErrorCode ierr; 9182 9183 PetscFunctionBegin; 9184 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9185 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9186 for(p = pStart; p < pEnd; ++p) { 9187 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9188 } 9189 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9190 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9191 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9192 for(p = pStart; p < pEnd; ++p) { 9193 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9194 } 9195 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9196 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9197 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9198 PetscFunctionReturn(0); 9199 } 9200 9201 #undef __FUNCT__ 9202 #define __FUNCT__ "DMPlexGetCellNumbering" 9203 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9204 { 9205 DM_Plex *mesh = (DM_Plex *) dm->data; 9206 PetscInt cellHeight, cStart, cEnd, cMax; 9207 PetscErrorCode ierr; 9208 9209 PetscFunctionBegin; 9210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9211 if (!mesh->globalCellNumbers) { 9212 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9213 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9214 ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr); 9215 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9216 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9217 } 9218 *globalCellNumbers = mesh->globalCellNumbers; 9219 PetscFunctionReturn(0); 9220 } 9221 9222 #undef __FUNCT__ 9223 #define __FUNCT__ "DMPlexGetVertexNumbering" 9224 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9225 { 9226 DM_Plex *mesh = (DM_Plex *) dm->data; 9227 PetscInt vStart, vEnd, vMax; 9228 PetscErrorCode ierr; 9229 9230 PetscFunctionBegin; 9231 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9232 if (!mesh->globalVertexNumbers) { 9233 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9234 ierr = DMPlexGetVTKBounds(dm, PETSC_NULL, &vMax);CHKERRQ(ierr); 9235 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9236 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9237 } 9238 *globalVertexNumbers = mesh->globalVertexNumbers; 9239 PetscFunctionReturn(0); 9240 } 9241 9242 #undef __FUNCT__ 9243 #define __FUNCT__ "DMPlexGetSubpointMap" 9244 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 9245 { 9246 DM_Plex *mesh = (DM_Plex *) dm->data; 9247 9248 PetscFunctionBegin; 9249 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9250 PetscValidPointer(subpointMap, 2); 9251 *subpointMap = mesh->subpointMap; 9252 PetscFunctionReturn(0); 9253 } 9254 9255 #undef __FUNCT__ 9256 #define __FUNCT__ "DMPlexSetSubpointMap" 9257 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 9258 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 9259 { 9260 DM_Plex *mesh = (DM_Plex *) dm->data; 9261 9262 PetscFunctionBegin; 9263 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9264 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 9265 mesh->subpointMap = subpointMap; 9266 PetscFunctionReturn(0); 9267 } 9268 9269 #undef __FUNCT__ 9270 #define __FUNCT__ "DMPlexGetScale" 9271 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9272 { 9273 DM_Plex *mesh = (DM_Plex *) dm->data; 9274 9275 PetscFunctionBegin; 9276 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9277 PetscValidPointer(scale, 3); 9278 *scale = mesh->scale[unit]; 9279 PetscFunctionReturn(0); 9280 } 9281 9282 #undef __FUNCT__ 9283 #define __FUNCT__ "DMPlexSetScale" 9284 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9285 { 9286 DM_Plex *mesh = (DM_Plex *) dm->data; 9287 9288 PetscFunctionBegin; 9289 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9290 mesh->scale[unit] = scale; 9291 PetscFunctionReturn(0); 9292 } 9293 9294 9295 /******************************************************************************* 9296 This should be in a separate Discretization object, but I am not sure how to lay 9297 it out yet, so I am stuffing things here while I experiment. 9298 *******************************************************************************/ 9299 #undef __FUNCT__ 9300 #define __FUNCT__ "DMPlexSetFEMIntegration" 9301 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9302 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9303 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9304 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9305 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9306 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9307 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9308 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9309 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9310 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9311 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9312 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9313 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9314 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9315 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9316 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9317 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9318 { 9319 DM_Plex *mesh = (DM_Plex *) dm->data; 9320 9321 PetscFunctionBegin; 9322 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9323 mesh->integrateResidualFEM = integrateResidualFEM; 9324 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9325 mesh->integrateJacobianFEM = integrateJacobianFEM; 9326 PetscFunctionReturn(0); 9327 } 9328 9329 #undef __FUNCT__ 9330 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9331 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9332 { 9333 Vec coordinates; 9334 PetscSection section, cSection; 9335 PetscInt dim, vStart, vEnd, v, c, d; 9336 PetscScalar *values, *cArray; 9337 PetscReal *coords; 9338 PetscErrorCode ierr; 9339 9340 PetscFunctionBegin; 9341 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9342 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9343 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9344 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9345 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9346 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9347 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9348 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9349 for (v = vStart; v < vEnd; ++v) { 9350 PetscInt dof, off; 9351 9352 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9353 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9354 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9355 for(d = 0; d < dof; ++d) { 9356 coords[d] = PetscRealPart(cArray[off+d]); 9357 } 9358 for(c = 0; c < numComp; ++c) { 9359 values[c] = (*funcs[c])(coords); 9360 } 9361 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9362 } 9363 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9364 /* Temporary, must be replaced by a projection on the finite element basis */ 9365 { 9366 PetscInt eStart = 0, eEnd = 0, e, depth; 9367 9368 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9369 --depth; 9370 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9371 for (e = eStart; e < eEnd; ++e) { 9372 const PetscInt *cone = PETSC_NULL; 9373 PetscInt coneSize, d; 9374 PetscScalar *coordsA, *coordsB; 9375 9376 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9377 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9378 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9379 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9380 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9381 for (d = 0; d < dim; ++d) { 9382 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9383 } 9384 for (c = 0; c < numComp; ++c) { 9385 values[c] = (*funcs[c])(coords); 9386 } 9387 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9388 } 9389 } 9390 9391 ierr = PetscFree(coords);CHKERRQ(ierr); 9392 ierr = PetscFree(values);CHKERRQ(ierr); 9393 #if 0 9394 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9395 PetscReal detJ; 9396 9397 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9398 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9399 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV((int) pow(this->_mesh->getSieve()->getMaxConeSize(), dim+1)+1, true); 9400 9401 for (PetscInt c = cStart; c < cEnd; ++c) { 9402 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9403 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9404 const int oSize = pV.getSize(); 9405 int v = 0; 9406 9407 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 9408 for (PetscInt cl = 0; cl < oSize; ++cl) { 9409 const PetscInt fDim; 9410 9411 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9412 if (pointDim) { 9413 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9414 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9415 } 9416 } 9417 } 9418 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 9419 pV.clear(); 9420 } 9421 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9422 ierr = PetscFree(values);CHKERRQ(ierr); 9423 #endif 9424 PetscFunctionReturn(0); 9425 } 9426 9427 #undef __FUNCT__ 9428 #define __FUNCT__ "DMPlexProjectFunction" 9429 /*@C 9430 DMPlexProjectFunction - This projects the given function into the function space provided. 9431 9432 Input Parameters: 9433 + dm - The DM 9434 . numComp - The number of components (functions) 9435 . funcs - The coordinate functions to evaluate 9436 - mode - The insertion mode for values 9437 9438 Output Parameter: 9439 . X - vector 9440 9441 Level: developer 9442 9443 Note: 9444 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9445 We will eventually fix it. 9446 9447 ,seealso: DMPlexComputeL2Diff() 9448 */ 9449 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9450 { 9451 Vec localX; 9452 PetscErrorCode ierr; 9453 9454 PetscFunctionBegin; 9455 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9456 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9457 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9458 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9459 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9460 PetscFunctionReturn(0); 9461 } 9462 9463 #undef __FUNCT__ 9464 #define __FUNCT__ "DMPlexComputeL2Diff" 9465 /*@C 9466 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9467 9468 Input Parameters: 9469 + dm - The DM 9470 . quad - The PetscQuadrature object for each field 9471 . funcs - The functions to evaluate for each field component 9472 - X - The coefficient vector u_h 9473 9474 Output Parameter: 9475 . diff - The diff ||u - u_h||_2 9476 9477 Level: developer 9478 9479 .seealso: DMPlexProjectFunction() 9480 */ 9481 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) { 9482 const PetscInt debug = 0; 9483 PetscSection section; 9484 Vec localX; 9485 PetscReal *coords, *v0, *J, *invJ, detJ; 9486 PetscReal localDiff = 0.0; 9487 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9488 PetscErrorCode ierr; 9489 9490 PetscFunctionBegin; 9491 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9492 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9493 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9494 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9495 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9496 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9497 for (field = 0; field < numFields; ++field) { 9498 numComponents += quad[field].numComponents; 9499 } 9500 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9501 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9502 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9503 for (c = cStart; c < cEnd; ++c) { 9504 const PetscScalar *x; 9505 PetscReal elemDiff = 0.0; 9506 9507 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9508 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9509 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9510 9511 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9512 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9513 const PetscReal *quadPoints = quad[field].quadPoints; 9514 const PetscReal *quadWeights = quad[field].quadWeights; 9515 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9516 const PetscInt numBasisComps = quad[field].numComponents; 9517 const PetscReal *basis = quad[field].basis; 9518 PetscInt q, d, e, fc, f; 9519 9520 if (debug) { 9521 char title[1024]; 9522 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9523 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9524 } 9525 for (q = 0; q < numQuadPoints; ++q) { 9526 for (d = 0; d < dim; d++) { 9527 coords[d] = v0[d]; 9528 for (e = 0; e < dim; e++) { 9529 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9530 } 9531 } 9532 for (fc = 0; fc < numBasisComps; ++fc) { 9533 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9534 PetscReal interpolant = 0.0; 9535 for (f = 0; f < numBasisFuncs; ++f) { 9536 const PetscInt fidx = f*numBasisComps+fc; 9537 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9538 } 9539 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9540 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9541 } 9542 } 9543 comp += numBasisComps; 9544 fieldOffset += numBasisFuncs*numBasisComps; 9545 } 9546 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9547 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9548 localDiff += elemDiff; 9549 } 9550 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9551 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9552 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9553 *diff = PetscSqrtReal(*diff); 9554 PetscFunctionReturn(0); 9555 } 9556 9557 #undef __FUNCT__ 9558 #define __FUNCT__ "DMPlexComputeResidualFEM" 9559 /*@ 9560 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9561 9562 Input Parameters: 9563 + dm - The mesh 9564 . X - Local input vector 9565 - user - The user context 9566 9567 Output Parameter: 9568 . F - Local output vector 9569 9570 Note: 9571 The second member of the user context must be an FEMContext. 9572 9573 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9574 like a GPU, or vectorize on a multicore machine. 9575 9576 .seealso: DMPlexComputeJacobianActionFEM() 9577 */ 9578 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9579 { 9580 DM_Plex *mesh = (DM_Plex *) dm->data; 9581 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9582 PetscQuadrature *quad = fem->quad; 9583 PetscSection section; 9584 PetscReal *v0, *J, *invJ, *detJ; 9585 PetscScalar *elemVec, *u; 9586 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9587 PetscInt cellDof = 0, numComponents = 0; 9588 PetscErrorCode ierr; 9589 9590 PetscFunctionBegin; 9591 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9592 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9593 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9594 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9595 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9596 numCells = cEnd - cStart; 9597 for (field = 0; field < numFields; ++field) { 9598 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9599 numComponents += quad[field].numComponents; 9600 } 9601 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9602 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9603 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); 9604 for (c = cStart; c < cEnd; ++c) { 9605 const PetscScalar *x; 9606 PetscInt i; 9607 9608 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9609 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9610 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9611 9612 for (i = 0; i < cellDof; ++i) { 9613 u[c*cellDof+i] = x[i]; 9614 } 9615 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9616 } 9617 for (field = 0; field < numFields; ++field) { 9618 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9619 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9620 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9621 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9622 /* Conforming batches */ 9623 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9624 PetscInt numBlocks = 1; 9625 PetscInt batchSize = numBlocks * blockSize; 9626 PetscInt numBatches = numBatchesTmp; 9627 PetscInt numChunks = numCells / (numBatches*batchSize); 9628 /* Remainder */ 9629 PetscInt numRemainder = numCells % (numBatches * batchSize); 9630 PetscInt offset = numCells - numRemainder; 9631 9632 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9633 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9634 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9635 } 9636 for (c = cStart; c < cEnd; ++c) { 9637 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9638 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9639 } 9640 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9641 if (mesh->printFEM) { 9642 PetscMPIInt rank, numProcs; 9643 PetscInt p; 9644 9645 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9646 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9647 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9648 for (p = 0; p < numProcs; ++p) { 9649 if (p == rank) { 9650 Vec f; 9651 9652 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9653 ierr = VecCopy(F, f);CHKERRQ(ierr); 9654 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9655 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9656 ierr = VecDestroy(&f);CHKERRQ(ierr); 9657 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9658 } 9659 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9660 } 9661 } 9662 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9663 PetscFunctionReturn(0); 9664 } 9665 9666 #undef __FUNCT__ 9667 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9668 /*@C 9669 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9670 9671 Input Parameters: 9672 + dm - The mesh 9673 . J - The Jacobian shell matrix 9674 . X - Local input vector 9675 - user - The user context 9676 9677 Output Parameter: 9678 . F - Local output vector 9679 9680 Note: 9681 The second member of the user context must be an FEMContext. 9682 9683 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9684 like a GPU, or vectorize on a multicore machine. 9685 9686 .seealso: DMPlexComputeResidualFEM() 9687 */ 9688 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9689 { 9690 DM_Plex *mesh = (DM_Plex *) dm->data; 9691 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9692 PetscQuadrature *quad = fem->quad; 9693 PetscSection section; 9694 JacActionCtx *jctx; 9695 PetscReal *v0, *J, *invJ, *detJ; 9696 PetscScalar *elemVec, *u, *a; 9697 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9698 PetscInt cellDof = 0; 9699 PetscErrorCode ierr; 9700 9701 PetscFunctionBegin; 9702 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9703 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9704 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9705 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9706 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9707 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9708 numCells = cEnd - cStart; 9709 for (field = 0; field < numFields; ++field) { 9710 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9711 } 9712 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9713 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); 9714 for (c = cStart; c < cEnd; ++c) { 9715 const PetscScalar *x; 9716 PetscInt i; 9717 9718 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9719 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9720 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9721 for (i = 0; i < cellDof; ++i) { 9722 u[c*cellDof+i] = x[i]; 9723 } 9724 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9725 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9726 for (i = 0; i < cellDof; ++i) { 9727 a[c*cellDof+i] = x[i]; 9728 } 9729 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9730 } 9731 for (field = 0; field < numFields; ++field) { 9732 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9733 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9734 /* Conforming batches */ 9735 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9736 PetscInt numBlocks = 1; 9737 PetscInt batchSize = numBlocks * blockSize; 9738 PetscInt numBatches = numBatchesTmp; 9739 PetscInt numChunks = numCells / (numBatches*batchSize); 9740 /* Remainder */ 9741 PetscInt numRemainder = numCells % (numBatches * batchSize); 9742 PetscInt offset = numCells - numRemainder; 9743 9744 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); 9745 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], 9746 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9747 } 9748 for (c = cStart; c < cEnd; ++c) { 9749 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9750 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9751 } 9752 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9753 if (mesh->printFEM) { 9754 PetscMPIInt rank, numProcs; 9755 PetscInt p; 9756 9757 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9758 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9759 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9760 for (p = 0; p < numProcs; ++p) { 9761 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9762 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9763 } 9764 } 9765 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9766 PetscFunctionReturn(0); 9767 } 9768 9769 #undef __FUNCT__ 9770 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9771 /*@ 9772 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9773 9774 Input Parameters: 9775 + dm - The mesh 9776 . X - Local input vector 9777 - user - The user context 9778 9779 Output Parameter: 9780 . Jac - Jacobian matrix 9781 9782 Note: 9783 The second member of the user context must be an FEMContext. 9784 9785 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9786 like a GPU, or vectorize on a multicore machine. 9787 9788 .seealso: FormFunctionLocal() 9789 */ 9790 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9791 { 9792 DM_Plex *mesh = (DM_Plex *) dm->data; 9793 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9794 PetscQuadrature *quad = fem->quad; 9795 PetscSection section; 9796 PetscReal *v0, *J, *invJ, *detJ; 9797 PetscScalar *elemMat, *u; 9798 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9799 PetscInt cellDof = 0, numComponents = 0; 9800 PetscBool isShell; 9801 PetscErrorCode ierr; 9802 9803 PetscFunctionBegin; 9804 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9805 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9806 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9807 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9808 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9809 numCells = cEnd - cStart; 9810 for (field = 0; field < numFields; ++field) { 9811 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9812 numComponents += quad[field].numComponents; 9813 } 9814 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9815 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9816 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); 9817 for (c = cStart; c < cEnd; ++c) { 9818 const PetscScalar *x; 9819 PetscInt i; 9820 9821 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9822 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9823 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9824 9825 for (i = 0; i < cellDof; ++i) { 9826 u[c*cellDof+i] = x[i]; 9827 } 9828 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9829 } 9830 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9831 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9832 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9833 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9834 PetscInt fieldJ; 9835 9836 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9837 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9838 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9839 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9840 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9841 /* Conforming batches */ 9842 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9843 PetscInt numBlocks = 1; 9844 PetscInt batchSize = numBlocks * blockSize; 9845 PetscInt numBatches = numBatchesTmp; 9846 PetscInt numChunks = numCells / (numBatches*batchSize); 9847 /* Remainder */ 9848 PetscInt numRemainder = numCells % (numBatches * batchSize); 9849 PetscInt offset = numCells - numRemainder; 9850 9851 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9852 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9853 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9854 } 9855 } 9856 for (c = cStart; c < cEnd; ++c) { 9857 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9858 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9859 } 9860 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9861 9862 /* Assemble matrix, using the 2-step process: 9863 MatAssemblyBegin(), MatAssemblyEnd(). */ 9864 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9865 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9866 9867 if (mesh->printFEM) { 9868 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9869 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9870 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9871 } 9872 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9873 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9874 if (isShell) { 9875 JacActionCtx *jctx; 9876 9877 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9878 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9879 } 9880 *str = SAME_NONZERO_PATTERN; 9881 PetscFunctionReturn(0); 9882 } 9883 9884 9885 #undef __FUNCT__ 9886 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9887 /*@C 9888 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9889 the local section and an SF describing the section point overlap. 9890 9891 Input Parameters: 9892 + s - The PetscSection for the local field layout 9893 . sf - The SF describing parallel layout of the section points 9894 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9895 . label - The label specifying the points 9896 - labelValue - The label stratum specifying the points 9897 9898 Output Parameter: 9899 . gsection - The PetscSection for the global field layout 9900 9901 Note: This gives negative sizes and offsets to points not owned by this process 9902 9903 Level: developer 9904 9905 .seealso: PetscSectionCreate() 9906 @*/ 9907 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9908 { 9909 PetscInt *neg; 9910 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9911 PetscErrorCode ierr; 9912 9913 PetscFunctionBegin; 9914 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9915 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9916 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9917 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9918 /* Mark ghost points with negative dof */ 9919 for (p = pStart; p < pEnd; ++p) { 9920 PetscInt value; 9921 9922 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9923 if (value != labelValue) continue; 9924 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9925 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9926 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9927 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9928 neg[p-pStart] = -(dof+1); 9929 } 9930 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9931 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 9932 if (nroots >= 0) { 9933 if (nroots > pEnd - pStart) { 9934 PetscInt *tmpDof; 9935 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9936 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9937 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9938 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9939 for (p = pStart; p < pEnd; ++p) { 9940 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 9941 } 9942 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9943 } else { 9944 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9945 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9946 } 9947 } 9948 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9949 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9950 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9951 (*gsection)->atlasOff[p] = off; 9952 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9953 } 9954 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9955 globalOff -= off; 9956 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9957 (*gsection)->atlasOff[p] += globalOff; 9958 neg[p] = -((*gsection)->atlasOff[p]+1); 9959 } 9960 /* Put in negative offsets for ghost points */ 9961 if (nroots >= 0) { 9962 if (nroots > pEnd - pStart) { 9963 PetscInt *tmpOff; 9964 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9965 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9966 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9967 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9968 for (p = pStart; p < pEnd; ++p) { 9969 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 9970 } 9971 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9972 } else { 9973 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9974 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9975 } 9976 } 9977 ierr = PetscFree(neg);CHKERRQ(ierr); 9978 PetscFunctionReturn(0); 9979 } 9980