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 = PetscRealPart(coords[faces[2*f+0]*2+0]); 7315 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7316 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7317 PetscReal y_j = PetscRealPart(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 PetscBool found = PETSC_TRUE; 7369 PetscInt f; 7370 PetscErrorCode ierr; 7371 7372 PetscFunctionBegin; 7373 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7374 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7375 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7376 for(f = 0; f < 6; ++f) { 7377 /* Check the point is under plane */ 7378 /* Get face normal */ 7379 PetscReal v_i[3] = {PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]), 7380 PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]), 7381 PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2])}; 7382 PetscReal v_j[3] = {PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]), 7383 PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]), 7384 PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2])}; 7385 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]}; 7386 PetscReal pp[3] = {PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]), 7387 PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]), 7388 PetscRealPart(coords[faces[f*4+0]*3+2] - point[2])}; 7389 PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7390 /* Check that projected point is in face (2D location problem) */ 7391 if (dot < 0.0) { 7392 found = PETSC_FALSE; 7393 break; 7394 } 7395 } 7396 if (found) { 7397 *cell = c; 7398 } else { 7399 *cell = -1; 7400 } 7401 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7402 PetscFunctionReturn(0); 7403 } 7404 7405 #undef __FUNCT__ 7406 #define __FUNCT__ "DMLocatePoints_Plex" 7407 /* 7408 Need to implement using the guess 7409 */ 7410 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7411 { 7412 PetscInt cell = -1/*, guess = -1*/; 7413 PetscInt bs, numPoints, p; 7414 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7415 PetscInt *cells; 7416 PetscScalar *a; 7417 PetscErrorCode ierr; 7418 7419 PetscFunctionBegin; 7420 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7421 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7422 ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr); 7423 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7424 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7425 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7426 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); 7427 numPoints /= bs; 7428 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7429 for(p = 0; p < numPoints; ++p) { 7430 const PetscScalar *point = &a[p*bs]; 7431 7432 switch(dim) { 7433 case 2: 7434 for(c = cStart; c < cEnd; ++c) { 7435 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7436 switch(coneSize) { 7437 case 3: 7438 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7439 break; 7440 case 4: 7441 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7442 break; 7443 default: 7444 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7445 } 7446 if (cell >= 0) break; 7447 } 7448 break; 7449 case 3: 7450 for(c = cStart; c < cEnd; ++c) { 7451 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7452 switch(coneSize) { 7453 case 4: 7454 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 7455 break; 7456 case 8: 7457 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 7458 break; 7459 default: 7460 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7461 } 7462 if (cell >= 0) break; 7463 } 7464 break; 7465 default: 7466 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 7467 } 7468 cells[p] = cell; 7469 } 7470 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 7471 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 7472 PetscFunctionReturn(0); 7473 } 7474 7475 /******************************** FEM Support **********************************/ 7476 7477 #undef __FUNCT__ 7478 #define __FUNCT__ "DMPlexVecGetClosure" 7479 /*@C 7480 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 7481 7482 Not collective 7483 7484 Input Parameters: 7485 + dm - The DM 7486 . section - The section describing the layout in v, or PETSC_NULL to use the default section 7487 . v - The local vector 7488 - point - The sieve point in the DM 7489 7490 Output Parameters: 7491 + csize - The number of values in the closure, or PETSC_NULL 7492 - values - The array of values, which is a borrowed array and should not be freed 7493 7494 Level: intermediate 7495 7496 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7497 @*/ 7498 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 7499 PetscScalar *array, *vArray; 7500 PetscInt *points = PETSC_NULL; 7501 PetscInt offsets[32]; 7502 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 7503 PetscErrorCode ierr; 7504 7505 PetscFunctionBegin; 7506 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7507 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7508 if (!section) { 7509 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7510 } 7511 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7512 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7513 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7514 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7515 /* Compress out points not in the section */ 7516 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7517 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7518 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7519 points[q*2] = points[p]; 7520 points[q*2+1] = points[p+1]; 7521 ++q; 7522 } 7523 } 7524 numPoints = q; 7525 for (p = 0, size = 0; p < numPoints*2; p += 2) { 7526 PetscInt dof, fdof; 7527 7528 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7529 for (f = 0; f < numFields; ++f) { 7530 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7531 offsets[f+1] += fdof; 7532 } 7533 size += dof; 7534 } 7535 for (f = 1; f < numFields; ++f) { 7536 offsets[f+1] += offsets[f]; 7537 } 7538 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 7539 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 7540 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 7541 for (p = 0; p < numPoints*2; p += 2) { 7542 PetscInt o = points[p+1]; 7543 PetscInt dof, off, d; 7544 PetscScalar *varr; 7545 7546 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7547 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 7548 varr = &vArray[off]; 7549 if (numFields) { 7550 PetscInt fdof, foff, fcomp, f, c; 7551 7552 for (f = 0, foff = 0; f < numFields; ++f) { 7553 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7554 if (o >= 0) { 7555 for (d = 0; d < fdof; ++d, ++offsets[f]) { 7556 array[offsets[f]] = varr[foff+d]; 7557 } 7558 } else { 7559 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7560 for (d = fdof/fcomp-1; d >= 0; --d) { 7561 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 7562 array[offsets[f]] = varr[foff+d*fcomp+c]; 7563 } 7564 } 7565 } 7566 foff += fdof; 7567 } 7568 } else { 7569 if (o >= 0) { 7570 for (d = 0; d < dof; ++d, ++offsets[0]) { 7571 array[offsets[0]] = varr[d]; 7572 } 7573 } else { 7574 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 7575 array[offsets[0]] = varr[d]; 7576 } 7577 } 7578 } 7579 } 7580 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7581 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 7582 if (csize) *csize = size; 7583 *values = array; 7584 PetscFunctionReturn(0); 7585 } 7586 7587 #undef __FUNCT__ 7588 #define __FUNCT__ "DMPlexVecRestoreClosure" 7589 /*@C 7590 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 7591 7592 Not collective 7593 7594 Input Parameters: 7595 + dm - The DM 7596 . section - The section describing the layout in v, or PETSC_NULL to use the default section 7597 . v - The local vector 7598 . point - The sieve point in the DM 7599 . csize - The number of values in the closure, or PETSC_NULL 7600 - values - The array of values, which is a borrowed array and should not be freed 7601 7602 Level: intermediate 7603 7604 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7605 @*/ 7606 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 7607 PetscInt size = 0; 7608 PetscErrorCode ierr; 7609 7610 PetscFunctionBegin; 7611 /* Should work without recalculating size */ 7612 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 7613 PetscFunctionReturn(0); 7614 } 7615 7616 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 7617 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 7618 7619 #undef __FUNCT__ 7620 #define __FUNCT__ "updatePoint_private" 7621 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 7622 { 7623 PetscInt cdof; /* The number of constraints on this point */ 7624 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7625 PetscScalar *a; 7626 PetscInt off, cind = 0, k; 7627 PetscErrorCode ierr; 7628 7629 PetscFunctionBegin; 7630 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 7631 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 7632 a = &array[off]; 7633 if (!cdof || setBC) { 7634 if (orientation >= 0) { 7635 for (k = 0; k < dof; ++k) { 7636 fuse(&a[k], values[k]); 7637 } 7638 } else { 7639 for (k = 0; k < dof; ++k) { 7640 fuse(&a[k], values[dof-k-1]); 7641 } 7642 } 7643 } else { 7644 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 7645 if (orientation >= 0) { 7646 for (k = 0; k < dof; ++k) { 7647 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7648 fuse(&a[k], values[k]); 7649 } 7650 } else { 7651 for (k = 0; k < dof; ++k) { 7652 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7653 fuse(&a[k], values[dof-k-1]); 7654 } 7655 } 7656 } 7657 PetscFunctionReturn(0); 7658 } 7659 7660 #undef __FUNCT__ 7661 #define __FUNCT__ "updatePointFields_private" 7662 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) { 7663 PetscScalar *a; 7664 PetscInt numFields, off, foff, f; 7665 PetscErrorCode ierr; 7666 7667 PetscFunctionBegin; 7668 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7669 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 7670 a = &array[off]; 7671 for (f = 0, foff = 0; f < numFields; ++f) { 7672 PetscInt fdof, fcomp, fcdof; 7673 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 7674 PetscInt cind = 0, k, c; 7675 7676 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7677 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 7678 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 7679 if (!fcdof || setBC) { 7680 if (orientation >= 0) { 7681 for (k = 0; k < fdof; ++k) { 7682 fuse(&a[foff+k], values[foffs[f]+k]); 7683 } 7684 } else { 7685 for (k = fdof/fcomp-1; k >= 0; --k) { 7686 for (c = 0; c < fcomp; ++c) { 7687 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 7688 } 7689 } 7690 } 7691 } else { 7692 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 7693 if (orientation >= 0) { 7694 for (k = 0; k < fdof; ++k) { 7695 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 7696 fuse(&a[foff+k], values[foffs[f]+k]); 7697 } 7698 } else { 7699 for (k = fdof/fcomp-1; k >= 0; --k) { 7700 for (c = 0; c < fcomp; ++c) { 7701 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 7702 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 7703 } 7704 } 7705 } 7706 } 7707 foff += fdof; 7708 foffs[f] += fdof; 7709 } 7710 PetscFunctionReturn(0); 7711 } 7712 7713 #undef __FUNCT__ 7714 #define __FUNCT__ "DMPlexVecSetClosure" 7715 /*@C 7716 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 7717 7718 Not collective 7719 7720 Input Parameters: 7721 + dm - The DM 7722 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 7723 . v - The local vector 7724 . point - The sieve point in the DM 7725 . values - The array of values, which is a borrowed array and should not be freed 7726 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7727 7728 Level: intermediate 7729 7730 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 7731 @*/ 7732 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) { 7733 PetscScalar *array; 7734 PetscInt *points = PETSC_NULL; 7735 PetscInt offsets[32]; 7736 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 7737 PetscErrorCode ierr; 7738 7739 PetscFunctionBegin; 7740 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7741 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7742 if (!section) { 7743 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7744 } 7745 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7746 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7747 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7748 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7749 /* Compress out points not in the section */ 7750 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7751 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7752 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7753 points[q*2] = points[p]; 7754 points[q*2+1] = points[p+1]; 7755 ++q; 7756 } 7757 } 7758 numPoints = q; 7759 for (p = 0; p < numPoints*2; p += 2) { 7760 PetscInt fdof; 7761 7762 for (f = 0; f < numFields; ++f) { 7763 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7764 offsets[f+1] += fdof; 7765 } 7766 } 7767 for (f = 1; f < numFields; ++f) { 7768 offsets[f+1] += offsets[f]; 7769 } 7770 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 7771 if (numFields) { 7772 switch(mode) { 7773 case INSERT_VALUES: 7774 for (p = 0; p < numPoints*2; p += 2) { 7775 PetscInt o = points[p+1]; 7776 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 7777 } break; 7778 case INSERT_ALL_VALUES: 7779 for (p = 0; p < numPoints*2; p += 2) { 7780 PetscInt o = points[p+1]; 7781 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 7782 } break; 7783 case ADD_VALUES: 7784 for (p = 0; p < numPoints*2; p += 2) { 7785 PetscInt o = points[p+1]; 7786 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 7787 } break; 7788 case ADD_ALL_VALUES: 7789 for (p = 0; p < numPoints*2; p += 2) { 7790 PetscInt o = points[p+1]; 7791 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 7792 } break; 7793 default: 7794 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7795 } 7796 } else { 7797 switch(mode) { 7798 case INSERT_VALUES: 7799 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7800 PetscInt o = points[p+1]; 7801 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7802 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 7803 } break; 7804 case INSERT_ALL_VALUES: 7805 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7806 PetscInt o = points[p+1]; 7807 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7808 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 7809 } break; 7810 case ADD_VALUES: 7811 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7812 PetscInt o = points[p+1]; 7813 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7814 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 7815 } break; 7816 case ADD_ALL_VALUES: 7817 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7818 PetscInt o = points[p+1]; 7819 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7820 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 7821 } break; 7822 default: 7823 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7824 } 7825 } 7826 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7827 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 7828 PetscFunctionReturn(0); 7829 } 7830 7831 #undef __FUNCT__ 7832 #define __FUNCT__ "DMPlexPrintMatSetValues" 7833 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 7834 { 7835 PetscMPIInt rank; 7836 PetscInt i, j; 7837 PetscErrorCode ierr; 7838 7839 PetscFunctionBegin; 7840 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 7841 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 7842 for (i = 0; i < numIndices; i++) { 7843 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 7844 } 7845 for (i = 0; i < numIndices; i++) { 7846 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 7847 for (j = 0; j < numIndices; j++) { 7848 #ifdef PETSC_USE_COMPLEX 7849 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 7850 #else 7851 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 7852 #endif 7853 } 7854 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 7855 } 7856 PetscFunctionReturn(0); 7857 } 7858 7859 #undef __FUNCT__ 7860 #define __FUNCT__ "indicesPoint_private" 7861 /* . off - The global offset of this point */ 7862 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 7863 PetscInt cdof; /* The number of constraints on this point */ 7864 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7865 PetscInt cind = 0, k; 7866 PetscErrorCode ierr; 7867 7868 PetscFunctionBegin; 7869 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 7870 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 7871 if (!cdof || setBC) { 7872 if (orientation >= 0) { 7873 for (k = 0; k < dof; ++k) { 7874 indices[k] = off+k; 7875 } 7876 } else { 7877 for (k = 0; k < dof; ++k) { 7878 indices[dof-k-1] = off+k; 7879 } 7880 } 7881 } else { 7882 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 7883 if (orientation >= 0) { 7884 for (k = 0; k < dof; ++k) { 7885 if ((cind < cdof) && (k == cdofs[cind])) { 7886 /* Insert check for returning constrained indices */ 7887 indices[k] = -(off+k+1); 7888 ++cind; 7889 } else { 7890 indices[k] = off+k-cind; 7891 } 7892 } 7893 } else { 7894 for (k = 0; k < dof; ++k) { 7895 if ((cind < cdof) && (k == cdofs[cind])) { 7896 /* Insert check for returning constrained indices */ 7897 indices[dof-k-1] = -(off+k+1); 7898 ++cind; 7899 } else { 7900 indices[dof-k-1] = off+k-cind; 7901 } 7902 } 7903 } 7904 } 7905 PetscFunctionReturn(0); 7906 } 7907 7908 #undef __FUNCT__ 7909 #define __FUNCT__ "indicesPointFields_private" 7910 /* . off - The global offset of this point */ 7911 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 7912 PetscInt numFields, foff, f; 7913 PetscErrorCode ierr; 7914 7915 PetscFunctionBegin; 7916 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7917 for (f = 0, foff = 0; f < numFields; ++f) { 7918 PetscInt fdof, fcomp, cfdof; 7919 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 7920 PetscInt cind = 0, k, c; 7921 7922 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7923 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 7924 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 7925 if (!cfdof || setBC) { 7926 if (orientation >= 0) { 7927 for (k = 0; k < fdof; ++k) { 7928 indices[foffs[f]+k] = off+foff+k; 7929 } 7930 } else { 7931 for (k = fdof/fcomp-1; k >= 0; --k) { 7932 for (c = 0; c < fcomp; ++c) { 7933 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 7934 } 7935 } 7936 } 7937 } else { 7938 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 7939 if (orientation >= 0) { 7940 for (k = 0; k < fdof; ++k) { 7941 if ((cind < cfdof) && (k == fcdofs[cind])) { 7942 indices[foffs[f]+k] = -(off+foff+k+1); 7943 ++cind; 7944 } else { 7945 indices[foffs[f]+k] = off+foff+k-cind; 7946 } 7947 } 7948 } else { 7949 for (k = fdof/fcomp-1; k >= 0; --k) { 7950 for (c = 0; c < fcomp; ++c) { 7951 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 7952 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 7953 ++cind; 7954 } else { 7955 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 7956 } 7957 } 7958 } 7959 } 7960 } 7961 foff += fdof - cfdof; 7962 foffs[f] += fdof; 7963 } 7964 PetscFunctionReturn(0); 7965 } 7966 7967 #undef __FUNCT__ 7968 #define __FUNCT__ "DMPlexMatSetClosure" 7969 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 7970 { 7971 DM_Plex *mesh = (DM_Plex *) dm->data; 7972 PetscInt *points = PETSC_NULL; 7973 PetscInt *indices; 7974 PetscInt offsets[32]; 7975 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 7976 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 7977 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 7978 PetscErrorCode ierr; 7979 7980 PetscFunctionBegin; 7981 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7982 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 7983 if (useDefault) { 7984 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7985 } 7986 if (useGlobalDefault) { 7987 if (useDefault) { 7988 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 7989 } else { 7990 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7991 } 7992 } 7993 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7994 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7995 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7996 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7997 /* Compress out points not in the section */ 7998 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7999 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8000 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8001 points[q*2] = points[p]; 8002 points[q*2+1] = points[p+1]; 8003 ++q; 8004 } 8005 } 8006 numPoints = q; 8007 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8008 PetscInt fdof; 8009 8010 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8011 for (f = 0; f < numFields; ++f) { 8012 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8013 offsets[f+1] += fdof; 8014 } 8015 numIndices += dof; 8016 } 8017 for (f = 1; f < numFields; ++f) { 8018 offsets[f+1] += offsets[f]; 8019 } 8020 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8021 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8022 if (numFields) { 8023 for (p = 0; p < numPoints*2; p += 2) { 8024 PetscInt o = points[p+1]; 8025 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8026 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8027 } 8028 } else { 8029 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8030 PetscInt o = points[p+1]; 8031 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8032 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8033 } 8034 } 8035 if (useGlobalDefault && !useDefault) { 8036 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8037 } 8038 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8039 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8040 if (ierr) { 8041 PetscMPIInt rank; 8042 PetscErrorCode ierr2; 8043 8044 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8045 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8046 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8047 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8048 CHKERRQ(ierr); 8049 } 8050 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8051 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8052 PetscFunctionReturn(0); 8053 } 8054 8055 #undef __FUNCT__ 8056 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8057 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8058 { 8059 PetscSection coordSection; 8060 Vec coordinates; 8061 const PetscScalar *coords; 8062 const PetscInt dim = 2; 8063 PetscInt d, f; 8064 PetscErrorCode ierr; 8065 8066 PetscFunctionBegin; 8067 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8068 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8069 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8070 if (v0) { 8071 for (d = 0; d < dim; d++) { 8072 v0[d] = PetscRealPart(coords[d]); 8073 } 8074 } 8075 if (J) { 8076 for (d = 0; d < dim; d++) { 8077 for (f = 0; f < dim; f++) { 8078 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8079 } 8080 } 8081 *detJ = J[0]*J[3] - J[1]*J[2]; 8082 #if 0 8083 if (detJ < 0.0) { 8084 const PetscReal xLength = mesh->periodicity[0]; 8085 8086 if (xLength != 0.0) { 8087 PetscReal v0x = coords[0*dim+0]; 8088 8089 if (v0x == 0.0) { 8090 v0x = v0[0] = xLength; 8091 } 8092 for (f = 0; f < dim; f++) { 8093 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8094 8095 J[0*dim+f] = 0.5*(px - v0x); 8096 } 8097 } 8098 detJ = J[0]*J[3] - J[1]*J[2]; 8099 } 8100 #endif 8101 PetscLogFlops(8.0 + 3.0); 8102 } 8103 if (invJ) { 8104 const PetscReal invDet = 1.0/(*detJ); 8105 8106 invJ[0] = invDet*J[3]; 8107 invJ[1] = -invDet*J[1]; 8108 invJ[2] = -invDet*J[2]; 8109 invJ[3] = invDet*J[0]; 8110 PetscLogFlops(5.0); 8111 } 8112 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8113 PetscFunctionReturn(0); 8114 } 8115 8116 #undef __FUNCT__ 8117 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8118 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8119 { 8120 PetscSection coordSection; 8121 Vec coordinates; 8122 const PetscScalar *coords; 8123 const PetscInt dim = 2; 8124 PetscInt d, f; 8125 PetscErrorCode ierr; 8126 8127 PetscFunctionBegin; 8128 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8129 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8130 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8131 if (v0) { 8132 for (d = 0; d < dim; d++) { 8133 v0[d] = PetscRealPart(coords[d]); 8134 } 8135 } 8136 if (J) { 8137 for (d = 0; d < dim; d++) { 8138 for (f = 0; f < dim; f++) { 8139 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8140 } 8141 } 8142 *detJ = J[0]*J[3] - J[1]*J[2]; 8143 PetscLogFlops(8.0 + 3.0); 8144 } 8145 if (invJ) { 8146 const PetscReal invDet = 1.0/(*detJ); 8147 8148 invJ[0] = invDet*J[3]; 8149 invJ[1] = -invDet*J[1]; 8150 invJ[2] = -invDet*J[2]; 8151 invJ[3] = invDet*J[0]; 8152 PetscLogFlops(5.0); 8153 } 8154 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8155 PetscFunctionReturn(0); 8156 } 8157 8158 #undef __FUNCT__ 8159 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8160 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8161 { 8162 PetscSection coordSection; 8163 Vec coordinates; 8164 const PetscScalar *coords; 8165 const PetscInt dim = 3; 8166 PetscInt d, f; 8167 PetscErrorCode ierr; 8168 8169 PetscFunctionBegin; 8170 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8171 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8172 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8173 if (v0) { 8174 for (d = 0; d < dim; d++) { 8175 v0[d] = PetscRealPart(coords[d]); 8176 } 8177 } 8178 if (J) { 8179 for (d = 0; d < dim; d++) { 8180 for (f = 0; f < dim; f++) { 8181 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8182 } 8183 } 8184 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8185 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8186 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8187 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8188 PetscLogFlops(18.0 + 12.0); 8189 } 8190 if (invJ) { 8191 const PetscReal invDet = -1.0/(*detJ); 8192 8193 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8194 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8195 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8196 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8197 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8198 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8199 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8200 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8201 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8202 PetscLogFlops(37.0); 8203 } 8204 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8205 PetscFunctionReturn(0); 8206 } 8207 8208 #undef __FUNCT__ 8209 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8210 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8211 { 8212 PetscSection coordSection; 8213 Vec coordinates; 8214 const PetscScalar *coords; 8215 const PetscInt dim = 3; 8216 PetscInt d; 8217 PetscErrorCode ierr; 8218 8219 PetscFunctionBegin; 8220 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8221 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8222 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8223 if (v0) { 8224 for (d = 0; d < dim; d++) { 8225 v0[d] = PetscRealPart(coords[d]); 8226 } 8227 } 8228 if (J) { 8229 for (d = 0; d < dim; d++) { 8230 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8231 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8232 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8233 } 8234 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8235 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8236 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8237 PetscLogFlops(18.0 + 12.0); 8238 } 8239 if (invJ) { 8240 const PetscReal invDet = -1.0/(*detJ); 8241 8242 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8243 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8244 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8245 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8246 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8247 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8248 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8249 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8250 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8251 PetscLogFlops(37.0); 8252 } 8253 *detJ *= 8.0; 8254 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8255 PetscFunctionReturn(0); 8256 } 8257 8258 #undef __FUNCT__ 8259 #define __FUNCT__ "DMPlexComputeCellGeometry" 8260 /*@C 8261 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8262 8263 Collective on DM 8264 8265 Input Arguments: 8266 + dm - the DM 8267 - cell - the cell 8268 8269 Output Arguments: 8270 + v0 - the translation part of this affine transform 8271 . J - the Jacobian of the transform to the reference element 8272 . invJ - the inverse of the Jacobian 8273 - detJ - the Jacobian determinant 8274 8275 Level: advanced 8276 8277 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8278 @*/ 8279 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) { 8280 PetscInt dim, maxConeSize; 8281 PetscErrorCode ierr; 8282 8283 PetscFunctionBegin; 8284 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8285 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 8286 switch(dim) { 8287 case 2: 8288 switch(maxConeSize) { 8289 case 3: 8290 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8291 break; 8292 case 4: 8293 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8294 break; 8295 default: 8296 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize); 8297 } 8298 break; 8299 case 3: 8300 switch(maxConeSize) { 8301 case 4: 8302 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8303 break; 8304 case 8: 8305 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8306 break; 8307 default: 8308 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize); 8309 } 8310 break; 8311 default: 8312 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8313 } 8314 PetscFunctionReturn(0); 8315 } 8316 8317 #undef __FUNCT__ 8318 #define __FUNCT__ "DMPlexGetFaceOrientation" 8319 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) { 8320 MPI_Comm comm = ((PetscObject) dm)->comm; 8321 PetscBool posOrient = PETSC_FALSE; 8322 const PetscInt debug = 0; 8323 PetscInt cellDim, faceSize, f; 8324 PetscErrorCode ierr; 8325 8326 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 8327 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 8328 8329 if (cellDim == numCorners-1) { 8330 /* Simplices */ 8331 faceSize = numCorners-1; 8332 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 8333 } else if (cellDim == 1 && numCorners == 3) { 8334 /* Quadratic line */ 8335 faceSize = 1; 8336 posOrient = PETSC_TRUE; 8337 } else if (cellDim == 2 && numCorners == 4) { 8338 /* Quads */ 8339 faceSize = 2; 8340 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 8341 posOrient = PETSC_TRUE; 8342 } else if ((indices[0] == 3) && (indices[1] == 0)) { 8343 posOrient = PETSC_TRUE; 8344 } else { 8345 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 8346 posOrient = PETSC_FALSE; 8347 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 8348 } 8349 } else if (cellDim == 2 && numCorners == 6) { 8350 /* Quadratic triangle (I hate this) */ 8351 /* Edges are determined by the first 2 vertices (corners of edges) */ 8352 const PetscInt faceSizeTri = 3; 8353 PetscInt sortedIndices[3], i, iFace; 8354 PetscBool found = PETSC_FALSE; 8355 PetscInt faceVerticesTriSorted[9] = { 8356 0, 3, 4, /* bottom */ 8357 1, 4, 5, /* right */ 8358 2, 3, 5, /* left */ 8359 }; 8360 PetscInt faceVerticesTri[9] = { 8361 0, 3, 4, /* bottom */ 8362 1, 4, 5, /* right */ 8363 2, 5, 3, /* left */ 8364 }; 8365 8366 faceSize = faceSizeTri; 8367 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 8368 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 8369 for (iFace = 0; iFace < 3; ++iFace) { 8370 const PetscInt ii = iFace*faceSizeTri; 8371 PetscInt fVertex, cVertex; 8372 8373 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 8374 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 8375 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 8376 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 8377 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 8378 faceVertices[fVertex] = origVertices[cVertex]; 8379 break; 8380 } 8381 } 8382 } 8383 found = PETSC_TRUE; 8384 break; 8385 } 8386 } 8387 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 8388 if (posOriented) {*posOriented = PETSC_TRUE;} 8389 PetscFunctionReturn(0); 8390 } else if (cellDim == 2 && numCorners == 9) { 8391 /* Quadratic quad (I hate this) */ 8392 /* Edges are determined by the first 2 vertices (corners of edges) */ 8393 const PetscInt faceSizeQuad = 3; 8394 PetscInt sortedIndices[3], i, iFace; 8395 PetscBool found = PETSC_FALSE; 8396 PetscInt faceVerticesQuadSorted[12] = { 8397 0, 1, 4, /* bottom */ 8398 1, 2, 5, /* right */ 8399 2, 3, 6, /* top */ 8400 0, 3, 7, /* left */ 8401 }; 8402 PetscInt faceVerticesQuad[12] = { 8403 0, 1, 4, /* bottom */ 8404 1, 2, 5, /* right */ 8405 2, 3, 6, /* top */ 8406 3, 0, 7, /* left */ 8407 }; 8408 8409 faceSize = faceSizeQuad; 8410 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 8411 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 8412 for (iFace = 0; iFace < 4; ++iFace) { 8413 const PetscInt ii = iFace*faceSizeQuad; 8414 PetscInt fVertex, cVertex; 8415 8416 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 8417 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 8418 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 8419 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 8420 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 8421 faceVertices[fVertex] = origVertices[cVertex]; 8422 break; 8423 } 8424 } 8425 } 8426 found = PETSC_TRUE; 8427 break; 8428 } 8429 } 8430 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 8431 if (posOriented) {*posOriented = PETSC_TRUE;} 8432 PetscFunctionReturn(0); 8433 } else if (cellDim == 3 && numCorners == 8) { 8434 /* Hexes 8435 A hex is two oriented quads with the normal of the first 8436 pointing up at the second. 8437 8438 7---6 8439 /| /| 8440 4---5 | 8441 | 3-|-2 8442 |/ |/ 8443 0---1 8444 8445 Faces are determined by the first 4 vertices (corners of faces) */ 8446 const PetscInt faceSizeHex = 4; 8447 PetscInt sortedIndices[4], i, iFace; 8448 PetscBool found = PETSC_FALSE; 8449 PetscInt faceVerticesHexSorted[24] = { 8450 0, 1, 2, 3, /* bottom */ 8451 4, 5, 6, 7, /* top */ 8452 0, 1, 4, 5, /* front */ 8453 1, 2, 5, 6, /* right */ 8454 2, 3, 6, 7, /* back */ 8455 0, 3, 4, 7, /* left */ 8456 }; 8457 PetscInt faceVerticesHex[24] = { 8458 3, 2, 1, 0, /* bottom */ 8459 4, 5, 6, 7, /* top */ 8460 0, 1, 5, 4, /* front */ 8461 1, 2, 6, 5, /* right */ 8462 2, 3, 7, 6, /* back */ 8463 3, 0, 4, 7, /* left */ 8464 }; 8465 8466 faceSize = faceSizeHex; 8467 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 8468 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 8469 for (iFace = 0; iFace < 6; ++iFace) { 8470 const PetscInt ii = iFace*faceSizeHex; 8471 PetscInt fVertex, cVertex; 8472 8473 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 8474 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 8475 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 8476 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 8477 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 8478 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 8479 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 8480 faceVertices[fVertex] = origVertices[cVertex]; 8481 break; 8482 } 8483 } 8484 } 8485 found = PETSC_TRUE; 8486 break; 8487 } 8488 } 8489 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 8490 if (posOriented) {*posOriented = PETSC_TRUE;} 8491 PetscFunctionReturn(0); 8492 } else if (cellDim == 3 && numCorners == 10) { 8493 /* Quadratic tet */ 8494 /* Faces are determined by the first 3 vertices (corners of faces) */ 8495 const PetscInt faceSizeTet = 6; 8496 PetscInt sortedIndices[6], i, iFace; 8497 PetscBool found = PETSC_FALSE; 8498 PetscInt faceVerticesTetSorted[24] = { 8499 0, 1, 2, 6, 7, 8, /* bottom */ 8500 0, 3, 4, 6, 7, 9, /* front */ 8501 1, 4, 5, 7, 8, 9, /* right */ 8502 2, 3, 5, 6, 8, 9, /* left */ 8503 }; 8504 PetscInt faceVerticesTet[24] = { 8505 0, 1, 2, 6, 7, 8, /* bottom */ 8506 0, 4, 3, 6, 7, 9, /* front */ 8507 1, 5, 4, 7, 8, 9, /* right */ 8508 2, 3, 5, 8, 6, 9, /* left */ 8509 }; 8510 8511 faceSize = faceSizeTet; 8512 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 8513 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 8514 for (iFace=0; iFace < 4; ++iFace) { 8515 const PetscInt ii = iFace*faceSizeTet; 8516 PetscInt fVertex, cVertex; 8517 8518 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 8519 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 8520 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 8521 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 8522 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 8523 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 8524 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 8525 faceVertices[fVertex] = origVertices[cVertex]; 8526 break; 8527 } 8528 } 8529 } 8530 found = PETSC_TRUE; 8531 break; 8532 } 8533 } 8534 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 8535 if (posOriented) {*posOriented = PETSC_TRUE;} 8536 PetscFunctionReturn(0); 8537 } else if (cellDim == 3 && numCorners == 27) { 8538 /* Quadratic hexes (I hate this) 8539 A hex is two oriented quads with the normal of the first 8540 pointing up at the second. 8541 8542 7---6 8543 /| /| 8544 4---5 | 8545 | 3-|-2 8546 |/ |/ 8547 0---1 8548 8549 Faces are determined by the first 4 vertices (corners of faces) */ 8550 const PetscInt faceSizeQuadHex = 9; 8551 PetscInt sortedIndices[9], i, iFace; 8552 PetscBool found = PETSC_FALSE; 8553 PetscInt faceVerticesQuadHexSorted[54] = { 8554 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 8555 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 8556 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 8557 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 8558 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 8559 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 8560 }; 8561 PetscInt faceVerticesQuadHex[54] = { 8562 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 8563 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 8564 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 8565 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 8566 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 8567 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 8568 }; 8569 8570 faceSize = faceSizeQuadHex; 8571 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 8572 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 8573 for (iFace = 0; iFace < 6; ++iFace) { 8574 const PetscInt ii = iFace*faceSizeQuadHex; 8575 PetscInt fVertex, cVertex; 8576 8577 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 8578 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 8579 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 8580 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 8581 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 8582 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 8583 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 8584 faceVertices[fVertex] = origVertices[cVertex]; 8585 break; 8586 } 8587 } 8588 } 8589 found = PETSC_TRUE; 8590 break; 8591 } 8592 } 8593 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 8594 if (posOriented) {*posOriented = PETSC_TRUE;} 8595 PetscFunctionReturn(0); 8596 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 8597 if (!posOrient) { 8598 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 8599 for (f = 0; f < faceSize; ++f) { 8600 faceVertices[f] = origVertices[faceSize-1 - f]; 8601 } 8602 } else { 8603 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 8604 for (f = 0; f < faceSize; ++f) { 8605 faceVertices[f] = origVertices[f]; 8606 } 8607 } 8608 if (posOriented) {*posOriented = posOrient;} 8609 PetscFunctionReturn(0); 8610 } 8611 8612 #undef __FUNCT__ 8613 #define __FUNCT__ "DMPlexGetOrientedFace" 8614 /* 8615 Given a cell and a face, as a set of vertices, 8616 return the oriented face, as a set of vertices, in faceVertices 8617 The orientation is such that the face normal points out of the cell 8618 */ 8619 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 8620 { 8621 const PetscInt *cone = PETSC_NULL; 8622 PetscInt coneSize, v, f, v2; 8623 PetscInt oppositeVertex = -1; 8624 PetscErrorCode ierr; 8625 8626 PetscFunctionBegin; 8627 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8628 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 8629 for (v = 0, v2 = 0; v < coneSize; ++v) { 8630 PetscBool found = PETSC_FALSE; 8631 8632 for (f = 0; f < faceSize; ++f) { 8633 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 8634 } 8635 if (found) { 8636 indices[v2] = v; 8637 origVertices[v2] = cone[v]; 8638 ++v2; 8639 } else { 8640 oppositeVertex = v; 8641 } 8642 } 8643 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 8644 PetscFunctionReturn(0); 8645 } 8646 8647 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8648 { 8649 switch(i) { 8650 case 0: 8651 switch(j) { 8652 case 0: return 0; 8653 case 1: 8654 switch(k) { 8655 case 0: return 0; 8656 case 1: return 0; 8657 case 2: return 1; 8658 } 8659 case 2: 8660 switch(k) { 8661 case 0: return 0; 8662 case 1: return -1; 8663 case 2: return 0; 8664 } 8665 } 8666 case 1: 8667 switch(j) { 8668 case 0: 8669 switch(k) { 8670 case 0: return 0; 8671 case 1: return 0; 8672 case 2: return -1; 8673 } 8674 case 1: return 0; 8675 case 2: 8676 switch(k) { 8677 case 0: return 1; 8678 case 1: return 0; 8679 case 2: return 0; 8680 } 8681 } 8682 case 2: 8683 switch(j) { 8684 case 0: 8685 switch(k) { 8686 case 0: return 0; 8687 case 1: return 1; 8688 case 2: return 0; 8689 } 8690 case 1: 8691 switch(k) { 8692 case 0: return -1; 8693 case 1: return 0; 8694 case 2: return 0; 8695 } 8696 case 2: return 0; 8697 } 8698 } 8699 return 0; 8700 } 8701 8702 #undef __FUNCT__ 8703 #define __FUNCT__ "DMPlexCreateRigidBody" 8704 /*@C 8705 DMPlexCreateRigidBody - create rigid body modes from coordinates 8706 8707 Collective on DM 8708 8709 Input Arguments: 8710 + dm - the DM 8711 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 8712 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 8713 8714 Output Argument: 8715 . sp - the null space 8716 8717 Note: This is necessary to take account of Dirichlet conditions on the displacements 8718 8719 Level: advanced 8720 8721 .seealso: MatNullSpaceCreate() 8722 @*/ 8723 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8724 { 8725 MPI_Comm comm = ((PetscObject) dm)->comm; 8726 Vec coordinates, localMode, mode[6]; 8727 PetscSection coordSection; 8728 PetscScalar *coords; 8729 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8730 PetscErrorCode ierr; 8731 8732 PetscFunctionBegin; 8733 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8734 if (dim == 1) { 8735 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 8736 PetscFunctionReturn(0); 8737 } 8738 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8739 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8740 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8741 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8742 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8743 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8744 m = (dim*(dim+1))/2; 8745 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8746 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8747 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8748 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8749 /* Assume P1 */ 8750 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8751 for (d = 0; d < dim; ++d) { 8752 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8753 8754 values[d] = 1.0; 8755 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8756 for (v = vStart; v < vEnd; ++v) { 8757 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8758 } 8759 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8760 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8761 } 8762 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8763 for (d = dim; d < dim*(dim+1)/2; ++d) { 8764 PetscInt i, j, k = dim > 2 ? d - dim : d; 8765 8766 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8767 for (v = vStart; v < vEnd; ++v) { 8768 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8769 PetscInt off; 8770 8771 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8772 for (i = 0; i < dim; ++i) { 8773 for (j = 0; j < dim; ++j) { 8774 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8775 } 8776 } 8777 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8778 } 8779 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8780 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8781 } 8782 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8783 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8784 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 8785 /* Orthonormalize system */ 8786 for (i = dim; i < m; ++i) { 8787 PetscScalar dots[6]; 8788 8789 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8790 for (j = 0; j < i; ++j) dots[j] *= -1.0; 8791 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8792 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 8793 } 8794 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 8795 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 8796 PetscFunctionReturn(0); 8797 } 8798 8799 #undef __FUNCT__ 8800 #define __FUNCT__ "DMPlexGetVTKBounds" 8801 PetscErrorCode DMPlexGetVTKBounds(DM dm, PetscInt *cMax, PetscInt *vMax) 8802 { 8803 DM_Plex *mesh = (DM_Plex *) dm->data; 8804 8805 PetscFunctionBegin; 8806 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8807 if (cMax) *cMax = mesh->vtkCellMax; 8808 if (vMax) *vMax = mesh->vtkVertexMax; 8809 PetscFunctionReturn(0); 8810 } 8811 8812 #undef __FUNCT__ 8813 #define __FUNCT__ "DMPlexSetVTKBounds" 8814 PetscErrorCode DMPlexSetVTKBounds(DM dm, PetscInt cMax, PetscInt vMax) 8815 { 8816 DM_Plex *mesh = (DM_Plex *) dm->data; 8817 8818 PetscFunctionBegin; 8819 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8820 if (cMax >= 0) mesh->vtkCellMax = cMax; 8821 if (vMax >= 0) mesh->vtkVertexMax = vMax; 8822 PetscFunctionReturn(0); 8823 } 8824 8825 #undef __FUNCT__ 8826 #define __FUNCT__ "DMPlexGetVTKCellHeight" 8827 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8828 { 8829 DM_Plex *mesh = (DM_Plex *) dm->data; 8830 8831 PetscFunctionBegin; 8832 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8833 PetscValidPointer(cellHeight, 2); 8834 *cellHeight = mesh->vtkCellHeight; 8835 PetscFunctionReturn(0); 8836 } 8837 8838 #undef __FUNCT__ 8839 #define __FUNCT__ "DMPlexSetVTKCellHeight" 8840 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8841 { 8842 DM_Plex *mesh = (DM_Plex *) dm->data; 8843 8844 PetscFunctionBegin; 8845 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8846 mesh->vtkCellHeight = cellHeight; 8847 PetscFunctionReturn(0); 8848 } 8849 8850 #undef __FUNCT__ 8851 #define __FUNCT__ "DMPlexInsertFace_Private" 8852 /* 8853 DMPlexInsertFace_Private - Puts a face into the mesh 8854 8855 Not collective 8856 8857 Input Parameters: 8858 + dm - The DMPlex 8859 . numFaceVertex - The number of vertices in the face 8860 . faceVertices - The vertices in the face for dm 8861 . subfaceVertices - The vertices in the face for subdm 8862 . numCorners - The number of vertices in the cell 8863 . cell - A cell in dm containing the face 8864 . subcell - A cell in subdm containing the face 8865 . firstFace - First face in the mesh 8866 - newFacePoint - Next face in the mesh 8867 8868 Output Parameters: 8869 . newFacePoint - Contains next face point number on input, updated on output 8870 8871 Level: developer 8872 */ 8873 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) 8874 { 8875 MPI_Comm comm = ((PetscObject) dm)->comm; 8876 DM_Plex *submesh = (DM_Plex *) subdm->data; 8877 const PetscInt *faces; 8878 PetscInt numFaces, coneSize; 8879 PetscErrorCode ierr; 8880 8881 PetscFunctionBegin; 8882 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 8883 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 8884 #if 0 8885 /* Cannot use this because support() has not been constructed yet */ 8886 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 8887 #else 8888 { 8889 PetscInt f; 8890 8891 numFaces = 0; 8892 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 8893 for(f = firstFace; f < *newFacePoint; ++f) { 8894 PetscInt dof, off, d; 8895 8896 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 8897 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 8898 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 8899 for(d = 0; d < dof; ++d) { 8900 const PetscInt p = submesh->cones[off+d]; 8901 PetscInt v; 8902 8903 for(v = 0; v < numFaceVertices; ++v) { 8904 if (subfaceVertices[v] == p) break; 8905 } 8906 if (v == numFaceVertices) break; 8907 } 8908 if (d == dof) { 8909 numFaces = 1; 8910 ((PetscInt *) faces)[0] = f; 8911 } 8912 } 8913 } 8914 #endif 8915 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 8916 else if (numFaces == 1) { 8917 /* Add the other cell neighbor for this face */ 8918 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 8919 } else { 8920 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 8921 PetscBool posOriented; 8922 8923 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 8924 origVertices = &orientedVertices[numFaceVertices]; 8925 indices = &orientedVertices[numFaceVertices*2]; 8926 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 8927 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 8928 /* TODO: I know that routine should return a permutation, not the indices */ 8929 for(v = 0; v < numFaceVertices; ++v) { 8930 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 8931 for(ov = 0; ov < numFaceVertices; ++ov) { 8932 if (orientedVertices[ov] == vertex) { 8933 orientedSubVertices[ov] = subvertex; 8934 break; 8935 } 8936 } 8937 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 8938 } 8939 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 8940 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 8941 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 8942 ++(*newFacePoint); 8943 } 8944 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 8945 PetscFunctionReturn(0); 8946 } 8947 8948 #undef __FUNCT__ 8949 #define __FUNCT__ "DMPlexCreateSubmesh" 8950 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 8951 { 8952 MPI_Comm comm = ((PetscObject) dm)->comm; 8953 DM_Plex *submesh; 8954 PetscBool boundaryFaces = PETSC_FALSE; 8955 PetscSection coordSection, subCoordSection; 8956 Vec coordinates, subCoordinates; 8957 PetscScalar *coords, *subCoords; 8958 IS labelIS; 8959 const PetscInt *subVertices; 8960 PetscInt *subVerticesActive, *tmpPoints; 8961 PetscInt *subCells = PETSC_NULL; 8962 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 8963 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 8964 PetscInt dim; /* Right now, do not specify dimension */ 8965 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 8966 PetscErrorCode ierr; 8967 8968 PetscFunctionBegin; 8969 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8970 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8971 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8972 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 8973 ierr = DMPlexGetVTKBounds(dm, &cMax, &vMax);CHKERRQ(ierr); 8974 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 8975 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 8976 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 8977 subface = &face[maxConeSize]; 8978 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 8979 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 8980 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 8981 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 8982 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 8983 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 8984 maxSubCells = numSubVertices; 8985 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 8986 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 8987 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 8988 for(v = 0; v < numSubVertices; ++v) { 8989 const PetscInt vertex = subVertices[v]; 8990 PetscInt *star = PETSC_NULL; 8991 PetscInt starSize, numCells = 0; 8992 8993 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 8994 for(p = 0; p < starSize*2; p += 2) { 8995 const PetscInt point = star[p]; 8996 if ((point >= cStart) && (point < cEnd)) { 8997 star[numCells++] = point; 8998 } 8999 } 9000 numOldSubCells = numSubCells; 9001 for(c = 0; c < numCells; ++c) { 9002 const PetscInt cell = star[c]; 9003 PetscInt *closure = PETSC_NULL; 9004 PetscInt closureSize, numCorners = 0, faceSize = 0; 9005 PetscInt cellLoc; 9006 9007 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 9008 if (cellLoc >= 0) continue; 9009 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9010 for(p = 0; p < closureSize*2; p += 2) { 9011 const PetscInt point = closure[p]; 9012 if ((point >= vStart) && (point < vEnd)) { 9013 closure[numCorners++] = point; 9014 } 9015 } 9016 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 9017 for(corner = 0; corner < numCorners; ++corner) { 9018 const PetscInt cellVertex = closure[corner]; 9019 PetscInt subVertex; 9020 9021 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 9022 if (subVertex >= 0) { /* contains submesh vertex */ 9023 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9024 if (i == faceSize) { 9025 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 9026 face[faceSize] = cellVertex; 9027 subface[faceSize] = subVertex; 9028 ++faceSize; 9029 } 9030 } 9031 } 9032 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9033 if (faceSize >= nFV) { 9034 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9035 if (numSubCells >= maxSubCells) { 9036 PetscInt *tmpCells; 9037 maxSubCells *= 2; 9038 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 9039 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 9040 ierr = PetscFree(subCells);CHKERRQ(ierr); 9041 subCells = tmpCells; 9042 } 9043 /* TOOD: Maybe overestimate then squeeze out empty faces */ 9044 if (faceSize > nFV) { 9045 /* TODO: This is tricky. Maybe just add all faces */ 9046 numSubFaces++; 9047 } else { 9048 numSubFaces++; 9049 } 9050 for(f = 0; f < faceSize; ++f) { 9051 subVerticesActive[subface[f]] = 1; 9052 } 9053 subCells[numSubCells++] = cell; 9054 } 9055 } 9056 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9057 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 9058 } 9059 /* Pick out active subvertices */ 9060 for(v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 9061 if (subVerticesActive[v]) { 9062 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 9063 } 9064 } 9065 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 9066 /* Set cone sizes */ 9067 firstSubVertex = numSubCells; 9068 firstSubFace = numSubCells+numSubVerticesActive; 9069 newFacePoint = firstSubFace; 9070 for(c = 0; c < numSubCells; ++c) { 9071 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 9072 } 9073 for(f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 9074 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 9075 } 9076 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 9077 /* Create face cones */ 9078 for(c = 0; c < numSubCells; ++c) { 9079 const PetscInt cell = subCells[c]; 9080 PetscInt *closure = PETSC_NULL; 9081 PetscInt closureSize, numCorners = 0, faceSize = 0; 9082 9083 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9084 for(p = 0; p < closureSize*2; p += 2) { 9085 const PetscInt point = closure[p]; 9086 if ((point >= vStart) && (point < vEnd)) { 9087 closure[numCorners++] = point; 9088 } 9089 } 9090 for(corner = 0; corner < numCorners; ++corner) { 9091 const PetscInt cellVertex = closure[corner]; 9092 PetscInt subVertex; 9093 9094 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 9095 if (subVertex >= 0) { /* contains submesh vertex */ 9096 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9097 if (i == faceSize) { 9098 face[faceSize] = cellVertex; 9099 subface[faceSize] = numSubCells+subVertex; 9100 ++faceSize; 9101 } 9102 } 9103 } 9104 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9105 if (faceSize >= nFV) { 9106 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9107 // Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) 9108 // We have to take all the faces, and discard those in the interior 9109 // We check the join of the face vertices, which produces 2 cells if in the interior 9110 #if 0 9111 // This object just calls insert on each face that comes from subsets() 9112 // In fact, we can just always acll subsets(), since when we pass a single face it is a single call 9113 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 9114 PointArray faceVec(face->begin(), face->end()); 9115 9116 subsets(faceVec, nFV, inserter); 9117 #endif 9118 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 9119 } 9120 } 9121 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 9122 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 9123 /* Build coordinates */ 9124 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9125 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9126 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 9127 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 9128 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 9129 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 9130 } 9131 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 9132 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 9133 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 9134 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 9135 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 9136 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9137 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9138 for(v = 0; v < numSubVerticesActive; ++v) { 9139 const PetscInt vertex = subVerticesActive[v]; 9140 const PetscInt subVertex = firstSubVertex+v; 9141 PetscInt dof, off, sdof, soff; 9142 9143 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 9144 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 9145 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 9146 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 9147 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 9148 for(d = 0; d < dof; ++d) { 9149 subCoords[soff+d] = coords[off+d]; 9150 } 9151 } 9152 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9153 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9154 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 9155 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 9156 9157 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 9158 /* Create map from submesh points to original mesh points */ 9159 submesh = (DM_Plex *) (*subdm)->data; 9160 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 9161 for(c = 0; c < numSubCells; ++c) { 9162 tmpPoints[c] = subCells[c]; 9163 } 9164 for(v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 9165 tmpPoints[v] = subVerticesActive[v-numSubCells]; 9166 } 9167 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 9168 9169 ierr = PetscFree(subCells);CHKERRQ(ierr); 9170 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 9171 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 9172 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 9173 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9174 PetscFunctionReturn(0); 9175 } 9176 9177 #undef __FUNCT__ 9178 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9179 /* We can easily have a form that takes an IS instead */ 9180 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9181 { 9182 PetscSection section, globalSection; 9183 PetscInt *numbers, p; 9184 PetscErrorCode ierr; 9185 9186 PetscFunctionBegin; 9187 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9188 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9189 for(p = pStart; p < pEnd; ++p) { 9190 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9191 } 9192 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9193 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9194 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9195 for(p = pStart; p < pEnd; ++p) { 9196 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9197 } 9198 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9199 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9200 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9201 PetscFunctionReturn(0); 9202 } 9203 9204 #undef __FUNCT__ 9205 #define __FUNCT__ "DMPlexGetCellNumbering" 9206 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9207 { 9208 DM_Plex *mesh = (DM_Plex *) dm->data; 9209 PetscInt cellHeight, cStart, cEnd, cMax; 9210 PetscErrorCode ierr; 9211 9212 PetscFunctionBegin; 9213 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9214 if (!mesh->globalCellNumbers) { 9215 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9216 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9217 ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr); 9218 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9219 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9220 } 9221 *globalCellNumbers = mesh->globalCellNumbers; 9222 PetscFunctionReturn(0); 9223 } 9224 9225 #undef __FUNCT__ 9226 #define __FUNCT__ "DMPlexGetVertexNumbering" 9227 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9228 { 9229 DM_Plex *mesh = (DM_Plex *) dm->data; 9230 PetscInt vStart, vEnd, vMax; 9231 PetscErrorCode ierr; 9232 9233 PetscFunctionBegin; 9234 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9235 if (!mesh->globalVertexNumbers) { 9236 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9237 ierr = DMPlexGetVTKBounds(dm, PETSC_NULL, &vMax);CHKERRQ(ierr); 9238 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9239 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9240 } 9241 *globalVertexNumbers = mesh->globalVertexNumbers; 9242 PetscFunctionReturn(0); 9243 } 9244 9245 #undef __FUNCT__ 9246 #define __FUNCT__ "DMPlexGetSubpointMap" 9247 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 9248 { 9249 DM_Plex *mesh = (DM_Plex *) dm->data; 9250 9251 PetscFunctionBegin; 9252 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9253 PetscValidPointer(subpointMap, 2); 9254 *subpointMap = mesh->subpointMap; 9255 PetscFunctionReturn(0); 9256 } 9257 9258 #undef __FUNCT__ 9259 #define __FUNCT__ "DMPlexSetSubpointMap" 9260 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 9261 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 9262 { 9263 DM_Plex *mesh = (DM_Plex *) dm->data; 9264 9265 PetscFunctionBegin; 9266 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9267 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 9268 mesh->subpointMap = subpointMap; 9269 PetscFunctionReturn(0); 9270 } 9271 9272 #undef __FUNCT__ 9273 #define __FUNCT__ "DMPlexGetScale" 9274 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9275 { 9276 DM_Plex *mesh = (DM_Plex *) dm->data; 9277 9278 PetscFunctionBegin; 9279 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9280 PetscValidPointer(scale, 3); 9281 *scale = mesh->scale[unit]; 9282 PetscFunctionReturn(0); 9283 } 9284 9285 #undef __FUNCT__ 9286 #define __FUNCT__ "DMPlexSetScale" 9287 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9288 { 9289 DM_Plex *mesh = (DM_Plex *) dm->data; 9290 9291 PetscFunctionBegin; 9292 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9293 mesh->scale[unit] = scale; 9294 PetscFunctionReturn(0); 9295 } 9296 9297 9298 /******************************************************************************* 9299 This should be in a separate Discretization object, but I am not sure how to lay 9300 it out yet, so I am stuffing things here while I experiment. 9301 *******************************************************************************/ 9302 #undef __FUNCT__ 9303 #define __FUNCT__ "DMPlexSetFEMIntegration" 9304 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9305 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9306 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9307 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9308 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9309 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9310 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9311 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9312 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9313 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9314 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9315 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9316 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9317 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9318 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9319 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9320 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9321 { 9322 DM_Plex *mesh = (DM_Plex *) dm->data; 9323 9324 PetscFunctionBegin; 9325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9326 mesh->integrateResidualFEM = integrateResidualFEM; 9327 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9328 mesh->integrateJacobianFEM = integrateJacobianFEM; 9329 PetscFunctionReturn(0); 9330 } 9331 9332 #undef __FUNCT__ 9333 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9334 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9335 { 9336 Vec coordinates; 9337 PetscSection section, cSection; 9338 PetscInt dim, vStart, vEnd, v, c, d; 9339 PetscScalar *values, *cArray; 9340 PetscReal *coords; 9341 PetscErrorCode ierr; 9342 9343 PetscFunctionBegin; 9344 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9345 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9346 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9347 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9348 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9349 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9350 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9351 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9352 for (v = vStart; v < vEnd; ++v) { 9353 PetscInt dof, off; 9354 9355 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9356 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9357 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9358 for(d = 0; d < dof; ++d) { 9359 coords[d] = PetscRealPart(cArray[off+d]); 9360 } 9361 for(c = 0; c < numComp; ++c) { 9362 values[c] = (*funcs[c])(coords); 9363 } 9364 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9365 } 9366 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9367 /* Temporary, must be replaced by a projection on the finite element basis */ 9368 { 9369 PetscInt eStart = 0, eEnd = 0, e, depth; 9370 9371 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9372 --depth; 9373 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9374 for (e = eStart; e < eEnd; ++e) { 9375 const PetscInt *cone = PETSC_NULL; 9376 PetscInt coneSize, d; 9377 PetscScalar *coordsA, *coordsB; 9378 9379 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9380 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9381 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9382 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9383 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9384 for (d = 0; d < dim; ++d) { 9385 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9386 } 9387 for (c = 0; c < numComp; ++c) { 9388 values[c] = (*funcs[c])(coords); 9389 } 9390 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9391 } 9392 } 9393 9394 ierr = PetscFree(coords);CHKERRQ(ierr); 9395 ierr = PetscFree(values);CHKERRQ(ierr); 9396 #if 0 9397 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9398 PetscReal detJ; 9399 9400 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9401 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9402 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV((int) pow(this->_mesh->getSieve()->getMaxConeSize(), dim+1)+1, true); 9403 9404 for (PetscInt c = cStart; c < cEnd; ++c) { 9405 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9406 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9407 const int oSize = pV.getSize(); 9408 int v = 0; 9409 9410 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 9411 for (PetscInt cl = 0; cl < oSize; ++cl) { 9412 const PetscInt fDim; 9413 9414 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9415 if (pointDim) { 9416 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9417 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9418 } 9419 } 9420 } 9421 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 9422 pV.clear(); 9423 } 9424 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9425 ierr = PetscFree(values);CHKERRQ(ierr); 9426 #endif 9427 PetscFunctionReturn(0); 9428 } 9429 9430 #undef __FUNCT__ 9431 #define __FUNCT__ "DMPlexProjectFunction" 9432 /*@C 9433 DMPlexProjectFunction - This projects the given function into the function space provided. 9434 9435 Input Parameters: 9436 + dm - The DM 9437 . numComp - The number of components (functions) 9438 . funcs - The coordinate functions to evaluate 9439 - mode - The insertion mode for values 9440 9441 Output Parameter: 9442 . X - vector 9443 9444 Level: developer 9445 9446 Note: 9447 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9448 We will eventually fix it. 9449 9450 ,seealso: DMPlexComputeL2Diff() 9451 */ 9452 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9453 { 9454 Vec localX; 9455 PetscErrorCode ierr; 9456 9457 PetscFunctionBegin; 9458 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9459 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9460 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9461 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9462 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9463 PetscFunctionReturn(0); 9464 } 9465 9466 #undef __FUNCT__ 9467 #define __FUNCT__ "DMPlexComputeL2Diff" 9468 /*@C 9469 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9470 9471 Input Parameters: 9472 + dm - The DM 9473 . quad - The PetscQuadrature object for each field 9474 . funcs - The functions to evaluate for each field component 9475 - X - The coefficient vector u_h 9476 9477 Output Parameter: 9478 . diff - The diff ||u - u_h||_2 9479 9480 Level: developer 9481 9482 .seealso: DMPlexProjectFunction() 9483 */ 9484 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) { 9485 const PetscInt debug = 0; 9486 PetscSection section; 9487 Vec localX; 9488 PetscReal *coords, *v0, *J, *invJ, detJ; 9489 PetscReal localDiff = 0.0; 9490 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9491 PetscErrorCode ierr; 9492 9493 PetscFunctionBegin; 9494 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9495 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9496 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9497 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9498 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9499 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9500 for (field = 0; field < numFields; ++field) { 9501 numComponents += quad[field].numComponents; 9502 } 9503 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9504 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9505 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9506 for (c = cStart; c < cEnd; ++c) { 9507 const PetscScalar *x; 9508 PetscReal elemDiff = 0.0; 9509 9510 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9511 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9512 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9513 9514 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9515 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9516 const PetscReal *quadPoints = quad[field].quadPoints; 9517 const PetscReal *quadWeights = quad[field].quadWeights; 9518 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9519 const PetscInt numBasisComps = quad[field].numComponents; 9520 const PetscReal *basis = quad[field].basis; 9521 PetscInt q, d, e, fc, f; 9522 9523 if (debug) { 9524 char title[1024]; 9525 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9526 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9527 } 9528 for (q = 0; q < numQuadPoints; ++q) { 9529 for (d = 0; d < dim; d++) { 9530 coords[d] = v0[d]; 9531 for (e = 0; e < dim; e++) { 9532 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9533 } 9534 } 9535 for (fc = 0; fc < numBasisComps; ++fc) { 9536 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9537 PetscReal interpolant = 0.0; 9538 for (f = 0; f < numBasisFuncs; ++f) { 9539 const PetscInt fidx = f*numBasisComps+fc; 9540 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9541 } 9542 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9543 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9544 } 9545 } 9546 comp += numBasisComps; 9547 fieldOffset += numBasisFuncs*numBasisComps; 9548 } 9549 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9550 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9551 localDiff += elemDiff; 9552 } 9553 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9554 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9555 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9556 *diff = PetscSqrtReal(*diff); 9557 PetscFunctionReturn(0); 9558 } 9559 9560 #undef __FUNCT__ 9561 #define __FUNCT__ "DMPlexComputeResidualFEM" 9562 /*@ 9563 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9564 9565 Input Parameters: 9566 + dm - The mesh 9567 . X - Local input vector 9568 - user - The user context 9569 9570 Output Parameter: 9571 . F - Local output vector 9572 9573 Note: 9574 The second member of the user context must be an FEMContext. 9575 9576 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9577 like a GPU, or vectorize on a multicore machine. 9578 9579 .seealso: DMPlexComputeJacobianActionFEM() 9580 */ 9581 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9582 { 9583 DM_Plex *mesh = (DM_Plex *) dm->data; 9584 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9585 PetscQuadrature *quad = fem->quad; 9586 PetscSection section; 9587 PetscReal *v0, *J, *invJ, *detJ; 9588 PetscScalar *elemVec, *u; 9589 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9590 PetscInt cellDof = 0, numComponents = 0; 9591 PetscErrorCode ierr; 9592 9593 PetscFunctionBegin; 9594 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9595 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9596 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9597 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9598 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9599 numCells = cEnd - cStart; 9600 for (field = 0; field < numFields; ++field) { 9601 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9602 numComponents += quad[field].numComponents; 9603 } 9604 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9605 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9606 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); 9607 for (c = cStart; c < cEnd; ++c) { 9608 const PetscScalar *x; 9609 PetscInt i; 9610 9611 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9612 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9613 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9614 9615 for (i = 0; i < cellDof; ++i) { 9616 u[c*cellDof+i] = x[i]; 9617 } 9618 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9619 } 9620 for (field = 0; field < numFields; ++field) { 9621 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9622 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9623 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9624 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9625 /* Conforming batches */ 9626 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9627 PetscInt numBlocks = 1; 9628 PetscInt batchSize = numBlocks * blockSize; 9629 PetscInt numBatches = numBatchesTmp; 9630 PetscInt numChunks = numCells / (numBatches*batchSize); 9631 /* Remainder */ 9632 PetscInt numRemainder = numCells % (numBatches * batchSize); 9633 PetscInt offset = numCells - numRemainder; 9634 9635 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9636 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9637 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9638 } 9639 for (c = cStart; c < cEnd; ++c) { 9640 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9641 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9642 } 9643 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9644 if (mesh->printFEM) { 9645 PetscMPIInt rank, numProcs; 9646 PetscInt p; 9647 9648 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9649 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9650 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9651 for (p = 0; p < numProcs; ++p) { 9652 if (p == rank) { 9653 Vec f; 9654 9655 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9656 ierr = VecCopy(F, f);CHKERRQ(ierr); 9657 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9658 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9659 ierr = VecDestroy(&f);CHKERRQ(ierr); 9660 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9661 } 9662 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9663 } 9664 } 9665 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9666 PetscFunctionReturn(0); 9667 } 9668 9669 #undef __FUNCT__ 9670 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9671 /*@C 9672 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9673 9674 Input Parameters: 9675 + dm - The mesh 9676 . J - The Jacobian shell matrix 9677 . X - Local input vector 9678 - user - The user context 9679 9680 Output Parameter: 9681 . F - Local output vector 9682 9683 Note: 9684 The second member of the user context must be an FEMContext. 9685 9686 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9687 like a GPU, or vectorize on a multicore machine. 9688 9689 .seealso: DMPlexComputeResidualFEM() 9690 */ 9691 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9692 { 9693 DM_Plex *mesh = (DM_Plex *) dm->data; 9694 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9695 PetscQuadrature *quad = fem->quad; 9696 PetscSection section; 9697 JacActionCtx *jctx; 9698 PetscReal *v0, *J, *invJ, *detJ; 9699 PetscScalar *elemVec, *u, *a; 9700 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9701 PetscInt cellDof = 0; 9702 PetscErrorCode ierr; 9703 9704 PetscFunctionBegin; 9705 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9706 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9707 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9708 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9709 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9710 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9711 numCells = cEnd - cStart; 9712 for (field = 0; field < numFields; ++field) { 9713 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9714 } 9715 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9716 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); 9717 for (c = cStart; c < cEnd; ++c) { 9718 const PetscScalar *x; 9719 PetscInt i; 9720 9721 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9722 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9723 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9724 for (i = 0; i < cellDof; ++i) { 9725 u[c*cellDof+i] = x[i]; 9726 } 9727 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9728 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9729 for (i = 0; i < cellDof; ++i) { 9730 a[c*cellDof+i] = x[i]; 9731 } 9732 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9733 } 9734 for (field = 0; field < numFields; ++field) { 9735 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9736 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9737 /* Conforming batches */ 9738 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9739 PetscInt numBlocks = 1; 9740 PetscInt batchSize = numBlocks * blockSize; 9741 PetscInt numBatches = numBatchesTmp; 9742 PetscInt numChunks = numCells / (numBatches*batchSize); 9743 /* Remainder */ 9744 PetscInt numRemainder = numCells % (numBatches * batchSize); 9745 PetscInt offset = numCells - numRemainder; 9746 9747 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); 9748 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], 9749 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9750 } 9751 for (c = cStart; c < cEnd; ++c) { 9752 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9753 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9754 } 9755 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9756 if (mesh->printFEM) { 9757 PetscMPIInt rank, numProcs; 9758 PetscInt p; 9759 9760 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9761 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9762 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9763 for (p = 0; p < numProcs; ++p) { 9764 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9765 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9766 } 9767 } 9768 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9769 PetscFunctionReturn(0); 9770 } 9771 9772 #undef __FUNCT__ 9773 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9774 /*@ 9775 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9776 9777 Input Parameters: 9778 + dm - The mesh 9779 . X - Local input vector 9780 - user - The user context 9781 9782 Output Parameter: 9783 . Jac - Jacobian matrix 9784 9785 Note: 9786 The second member of the user context must be an FEMContext. 9787 9788 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9789 like a GPU, or vectorize on a multicore machine. 9790 9791 .seealso: FormFunctionLocal() 9792 */ 9793 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9794 { 9795 DM_Plex *mesh = (DM_Plex *) dm->data; 9796 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9797 PetscQuadrature *quad = fem->quad; 9798 PetscSection section; 9799 PetscReal *v0, *J, *invJ, *detJ; 9800 PetscScalar *elemMat, *u; 9801 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9802 PetscInt cellDof = 0, numComponents = 0; 9803 PetscBool isShell; 9804 PetscErrorCode ierr; 9805 9806 PetscFunctionBegin; 9807 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9808 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9809 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9810 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9811 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9812 numCells = cEnd - cStart; 9813 for (field = 0; field < numFields; ++field) { 9814 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9815 numComponents += quad[field].numComponents; 9816 } 9817 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9818 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9819 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); 9820 for (c = cStart; c < cEnd; ++c) { 9821 const PetscScalar *x; 9822 PetscInt i; 9823 9824 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9825 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9826 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9827 9828 for (i = 0; i < cellDof; ++i) { 9829 u[c*cellDof+i] = x[i]; 9830 } 9831 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9832 } 9833 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9834 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9835 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9836 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9837 PetscInt fieldJ; 9838 9839 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9840 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9841 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9842 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9843 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9844 /* Conforming batches */ 9845 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9846 PetscInt numBlocks = 1; 9847 PetscInt batchSize = numBlocks * blockSize; 9848 PetscInt numBatches = numBatchesTmp; 9849 PetscInt numChunks = numCells / (numBatches*batchSize); 9850 /* Remainder */ 9851 PetscInt numRemainder = numCells % (numBatches * batchSize); 9852 PetscInt offset = numCells - numRemainder; 9853 9854 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9855 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9856 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9857 } 9858 } 9859 for (c = cStart; c < cEnd; ++c) { 9860 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9861 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9862 } 9863 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9864 9865 /* Assemble matrix, using the 2-step process: 9866 MatAssemblyBegin(), MatAssemblyEnd(). */ 9867 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9868 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9869 9870 if (mesh->printFEM) { 9871 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9872 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9873 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9874 } 9875 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9876 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9877 if (isShell) { 9878 JacActionCtx *jctx; 9879 9880 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9881 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9882 } 9883 *str = SAME_NONZERO_PATTERN; 9884 PetscFunctionReturn(0); 9885 } 9886 9887 9888 #undef __FUNCT__ 9889 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9890 /*@C 9891 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9892 the local section and an SF describing the section point overlap. 9893 9894 Input Parameters: 9895 + s - The PetscSection for the local field layout 9896 . sf - The SF describing parallel layout of the section points 9897 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9898 . label - The label specifying the points 9899 - labelValue - The label stratum specifying the points 9900 9901 Output Parameter: 9902 . gsection - The PetscSection for the global field layout 9903 9904 Note: This gives negative sizes and offsets to points not owned by this process 9905 9906 Level: developer 9907 9908 .seealso: PetscSectionCreate() 9909 @*/ 9910 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9911 { 9912 PetscInt *neg; 9913 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9914 PetscErrorCode ierr; 9915 9916 PetscFunctionBegin; 9917 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9918 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9919 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9920 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9921 /* Mark ghost points with negative dof */ 9922 for (p = pStart; p < pEnd; ++p) { 9923 PetscInt value; 9924 9925 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9926 if (value != labelValue) continue; 9927 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9928 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9929 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9930 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9931 neg[p-pStart] = -(dof+1); 9932 } 9933 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9934 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 9935 if (nroots >= 0) { 9936 if (nroots > pEnd - pStart) { 9937 PetscInt *tmpDof; 9938 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9939 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9940 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9941 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9942 for (p = pStart; p < pEnd; ++p) { 9943 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 9944 } 9945 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9946 } else { 9947 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9948 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9949 } 9950 } 9951 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9952 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9953 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9954 (*gsection)->atlasOff[p] = off; 9955 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9956 } 9957 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9958 globalOff -= off; 9959 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9960 (*gsection)->atlasOff[p] += globalOff; 9961 neg[p] = -((*gsection)->atlasOff[p]+1); 9962 } 9963 /* Put in negative offsets for ghost points */ 9964 if (nroots >= 0) { 9965 if (nroots > pEnd - pStart) { 9966 PetscInt *tmpOff; 9967 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9968 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9969 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9970 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9971 for (p = pStart; p < pEnd; ++p) { 9972 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 9973 } 9974 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9975 } else { 9976 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9977 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9978 } 9979 } 9980 ierr = PetscFree(neg);CHKERRQ(ierr); 9981 PetscFunctionReturn(0); 9982 } 9983