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