1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/isimpl.h> 4 #include <petscsf.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 8 9 PETSC_EXTERN PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "VecView_Plex_Local" 14 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 15 { 16 DM dm; 17 PetscBool isvtk; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 22 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 23 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 24 if (isvtk) { 25 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 26 PetscSection section; 27 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 28 29 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 30 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 31 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 32 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 33 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 34 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 35 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 36 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 37 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 38 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 39 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 40 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 41 } else if (cdof && vdof) { 42 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 43 } else if (cdof) { 44 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 45 * vector or just happens to have the same number of dofs as the dimension. */ 46 if (cdof == dim) { 47 ft = PETSC_VTK_CELL_VECTOR_FIELD; 48 } else { 49 ft = PETSC_VTK_CELL_FIELD; 50 } 51 } else if (vdof) { 52 if (vdof == dim) { 53 ft = PETSC_VTK_POINT_VECTOR_FIELD; 54 } else { 55 ft = PETSC_VTK_POINT_FIELD; 56 } 57 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 58 59 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 60 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 61 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 62 } else { 63 PetscBool isseq; 64 65 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 66 if (isseq) { 67 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 68 } else { 69 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 70 } 71 } 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "VecView_Plex" 77 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 78 { 79 DM dm; 80 PetscBool isvtk; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 85 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 86 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 87 if (isvtk) { 88 Vec locv; 89 const char *name; 90 91 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 92 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 93 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 94 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 95 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 96 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 97 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 98 } else { 99 PetscBool isseq; 100 101 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 102 if (isseq) { 103 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 104 } else { 105 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "DMPlexView_Ascii" 113 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 114 { 115 DM_Plex *mesh = (DM_Plex*) dm->data; 116 DM cdm; 117 DMLabel markers; 118 PetscSection coordSection; 119 Vec coordinates; 120 PetscViewerFormat format; 121 PetscErrorCode ierr; 122 123 PetscFunctionBegin; 124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 125 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 126 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 127 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 128 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 129 const char *name; 130 PetscInt maxConeSize, maxSupportSize; 131 PetscInt pStart, pEnd, p; 132 PetscMPIInt rank, size; 133 134 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 135 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 136 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 137 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 138 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 142 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 143 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 144 for (p = pStart; p < pEnd; ++p) { 145 PetscInt dof, off, s; 146 147 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 148 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 149 for (s = off; s < off+dof; ++s) { 150 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 151 } 152 } 153 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 154 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 155 for (p = pStart; p < pEnd; ++p) { 156 PetscInt dof, off, c; 157 158 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 159 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 160 for (c = off; c < off+dof; ++c) { 161 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 162 } 163 } 164 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 165 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 166 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 167 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 168 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 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(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for (v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for (e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), 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 = NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscInt numLabels, l; 282 PetscMPIInt size; 283 284 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 285 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 286 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 287 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 288 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 289 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 290 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 291 if (depth == 1) { 292 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 293 pEnd = pEnd - pStart; 294 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 295 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 296 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 297 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 298 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 299 pEnd = pEnd - pStart; 300 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 301 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 302 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 303 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 304 } else { 305 for (d = 0; d <= dim; d++) { 306 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 307 pEnd = pEnd - pStart; 308 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 309 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 310 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 311 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 312 } 313 } 314 ierr = PetscFree(sizes);CHKERRQ(ierr); 315 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 316 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 317 for (l = 0; l < numLabels; ++l) { 318 DMLabel label; 319 const char *name; 320 IS valueIS; 321 const PetscInt *values; 322 PetscInt numValues, v; 323 324 ierr = DMPlexGetLabelName(dm, l, &name);CHKERRQ(ierr); 325 ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); 326 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 327 ierr = PetscViewerASCIIPrintf(viewer, " %s: %d strata of sizes (", name, numValues);CHKERRQ(ierr); 328 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 329 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 330 for (v = 0; v < numValues; ++v) { 331 PetscInt size; 332 333 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 334 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 335 ierr = PetscViewerASCIIPrintf(viewer, "%d", size);CHKERRQ(ierr); 336 } 337 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 338 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 339 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 340 } 341 } 342 PetscFunctionReturn(0); 343 } 344 345 #undef __FUNCT__ 346 #define __FUNCT__ "DMView_Plex" 347 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 348 { 349 PetscBool iascii, isbinary; 350 PetscErrorCode ierr; 351 352 PetscFunctionBegin; 353 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 354 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 355 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 356 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 357 if (iascii) { 358 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 359 #if 0 360 } else if (isbinary) { 361 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 362 #endif 363 } 364 PetscFunctionReturn(0); 365 } 366 367 #undef __FUNCT__ 368 #define __FUNCT__ "DMDestroy_Plex" 369 PetscErrorCode DMDestroy_Plex(DM dm) 370 { 371 DM_Plex *mesh = (DM_Plex*) dm->data; 372 DMLabel next = mesh->labels; 373 PetscErrorCode ierr; 374 375 PetscFunctionBegin; 376 if (--mesh->refct > 0) PetscFunctionReturn(0); 377 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 378 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 379 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 380 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 381 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 382 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 383 while (next) { 384 DMLabel tmp = next->next; 385 386 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 387 next = tmp; 388 } 389 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 390 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 391 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 392 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 393 ierr = PetscFree(mesh);CHKERRQ(ierr); 394 PetscFunctionReturn(0); 395 } 396 397 #undef __FUNCT__ 398 #define __FUNCT__ "DMCreateMatrix_Plex" 399 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 400 { 401 PetscSection section, sectionGlobal; 402 PetscInt bs = -1; 403 PetscInt localSize; 404 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 405 PetscErrorCode ierr; 406 407 PetscFunctionBegin; 408 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 409 ierr = MatInitializePackage();CHKERRQ(ierr); 410 #endif 411 if (!mtype) mtype = MATAIJ; 412 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 413 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 414 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 415 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 416 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 417 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 418 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 419 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 420 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 421 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 422 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 423 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 424 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 425 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 426 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 427 /* Check for symmetric storage */ 428 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 429 if (isSymmetric) { 430 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 431 } 432 if (!isShell) { 433 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 434 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 435 436 if (bs < 0) { 437 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 438 PetscInt pStart, pEnd, p, dof, cdof; 439 440 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 441 for (p = pStart; p < pEnd; ++p) { 442 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 443 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 444 if (dof-cdof) { 445 if (bs < 0) { 446 bs = dof-cdof; 447 } else if (bs != dof-cdof) { 448 /* Layout does not admit a pointwise block size */ 449 bs = 1; 450 break; 451 } 452 } 453 } 454 /* Must have same blocksize on all procs (some might have no points) */ 455 bsLocal = bs; 456 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 457 bsLocal = bs < 0 ? bsMax : bs; 458 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 459 if (bsMin != bsMax) { 460 bs = 1; 461 } else { 462 bs = bsMax; 463 } 464 } else { 465 bs = 1; 466 } 467 } 468 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 469 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 470 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 471 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 472 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 473 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 474 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 475 } 476 PetscFunctionReturn(0); 477 } 478 479 #undef __FUNCT__ 480 #define __FUNCT__ "DMPlexGetDimension" 481 /*@ 482 DMPlexGetDimension - Return the topological mesh dimension 483 484 Not collective 485 486 Input Parameter: 487 . mesh - The DMPlex 488 489 Output Parameter: 490 . dim - The topological mesh dimension 491 492 Level: beginner 493 494 .seealso: DMPlexCreate() 495 @*/ 496 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 497 { 498 DM_Plex *mesh = (DM_Plex*) dm->data; 499 500 PetscFunctionBegin; 501 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 502 PetscValidPointer(dim, 2); 503 *dim = mesh->dim; 504 PetscFunctionReturn(0); 505 } 506 507 #undef __FUNCT__ 508 #define __FUNCT__ "DMPlexSetDimension" 509 /*@ 510 DMPlexSetDimension - Set the topological mesh dimension 511 512 Collective on mesh 513 514 Input Parameters: 515 + mesh - The DMPlex 516 - dim - The topological mesh dimension 517 518 Level: beginner 519 520 .seealso: DMPlexCreate() 521 @*/ 522 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 523 { 524 DM_Plex *mesh = (DM_Plex*) dm->data; 525 526 PetscFunctionBegin; 527 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 528 PetscValidLogicalCollectiveInt(dm, dim, 2); 529 mesh->dim = dim; 530 mesh->preallocCenterDim = dim; 531 PetscFunctionReturn(0); 532 } 533 534 #undef __FUNCT__ 535 #define __FUNCT__ "DMPlexGetChart" 536 /*@ 537 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 538 539 Not collective 540 541 Input Parameter: 542 . mesh - The DMPlex 543 544 Output Parameters: 545 + pStart - The first mesh point 546 - pEnd - The upper bound for mesh points 547 548 Level: beginner 549 550 .seealso: DMPlexCreate(), DMPlexSetChart() 551 @*/ 552 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 553 { 554 DM_Plex *mesh = (DM_Plex*) dm->data; 555 PetscErrorCode ierr; 556 557 PetscFunctionBegin; 558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 559 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 560 PetscFunctionReturn(0); 561 } 562 563 #undef __FUNCT__ 564 #define __FUNCT__ "DMPlexSetChart" 565 /*@ 566 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 567 568 Not collective 569 570 Input Parameters: 571 + mesh - The DMPlex 572 . pStart - The first mesh point 573 - pEnd - The upper bound for mesh points 574 575 Output Parameters: 576 577 Level: beginner 578 579 .seealso: DMPlexCreate(), DMPlexGetChart() 580 @*/ 581 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 582 { 583 DM_Plex *mesh = (DM_Plex*) dm->data; 584 PetscErrorCode ierr; 585 586 PetscFunctionBegin; 587 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 588 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 589 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 590 PetscFunctionReturn(0); 591 } 592 593 #undef __FUNCT__ 594 #define __FUNCT__ "DMPlexGetConeSize" 595 /*@ 596 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 597 598 Not collective 599 600 Input Parameters: 601 + mesh - The DMPlex 602 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 603 604 Output Parameter: 605 . size - The cone size for point p 606 607 Level: beginner 608 609 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 610 @*/ 611 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 612 { 613 DM_Plex *mesh = (DM_Plex*) dm->data; 614 PetscErrorCode ierr; 615 616 PetscFunctionBegin; 617 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 618 PetscValidPointer(size, 3); 619 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 620 PetscFunctionReturn(0); 621 } 622 623 #undef __FUNCT__ 624 #define __FUNCT__ "DMPlexSetConeSize" 625 /*@ 626 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 627 628 Not collective 629 630 Input Parameters: 631 + mesh - The DMPlex 632 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 633 - size - The cone size for point p 634 635 Output Parameter: 636 637 Note: 638 This should be called after DMPlexSetChart(). 639 640 Level: beginner 641 642 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 643 @*/ 644 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 645 { 646 DM_Plex *mesh = (DM_Plex*) dm->data; 647 PetscErrorCode ierr; 648 649 PetscFunctionBegin; 650 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 651 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 652 653 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 654 PetscFunctionReturn(0); 655 } 656 657 #undef __FUNCT__ 658 #define __FUNCT__ "DMPlexGetCone" 659 /*@C 660 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 661 662 Not collective 663 664 Input Parameters: 665 + mesh - The DMPlex 666 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 667 668 Output Parameter: 669 . cone - An array of points which are on the in-edges for point p 670 671 Level: beginner 672 673 Fortran Notes: 674 Since it returns an array, this routine is only available in Fortran 90, and you must 675 include petsc.h90 in your code. 676 677 You must also call DMPlexRestoreCone() after you finish using the returned array. 678 679 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 680 @*/ 681 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 682 { 683 DM_Plex *mesh = (DM_Plex*) dm->data; 684 PetscInt off; 685 PetscErrorCode ierr; 686 687 PetscFunctionBegin; 688 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 689 PetscValidPointer(cone, 3); 690 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 691 *cone = &mesh->cones[off]; 692 PetscFunctionReturn(0); 693 } 694 695 #undef __FUNCT__ 696 #define __FUNCT__ "DMPlexSetCone" 697 /*@ 698 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 699 700 Not collective 701 702 Input Parameters: 703 + mesh - The DMPlex 704 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 705 - cone - An array of points which are on the in-edges for point p 706 707 Output Parameter: 708 709 Note: 710 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 711 712 Level: beginner 713 714 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 715 @*/ 716 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 717 { 718 DM_Plex *mesh = (DM_Plex*) dm->data; 719 PetscInt pStart, pEnd; 720 PetscInt dof, off, c; 721 PetscErrorCode ierr; 722 723 PetscFunctionBegin; 724 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 725 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 726 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 727 if (dof) PetscValidPointer(cone, 3); 728 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 729 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 730 for (c = 0; c < dof; ++c) { 731 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 732 mesh->cones[off+c] = cone[c]; 733 } 734 PetscFunctionReturn(0); 735 } 736 737 #undef __FUNCT__ 738 #define __FUNCT__ "DMPlexGetConeOrientation" 739 /*@C 740 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 741 742 Not collective 743 744 Input Parameters: 745 + mesh - The DMPlex 746 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 747 748 Output Parameter: 749 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 750 integer giving the prescription for cone traversal. If it is negative, the cone is 751 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 752 the index of the cone point on which to start. 753 754 Level: beginner 755 756 Fortran Notes: 757 Since it returns an array, this routine is only available in Fortran 90, and you must 758 include petsc.h90 in your code. 759 760 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 761 762 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 763 @*/ 764 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 765 { 766 DM_Plex *mesh = (DM_Plex*) dm->data; 767 PetscInt off; 768 PetscErrorCode ierr; 769 770 PetscFunctionBegin; 771 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 772 #if defined(PETSC_USE_DEBUG) 773 { 774 PetscInt dof; 775 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 776 if (dof) PetscValidPointer(coneOrientation, 3); 777 } 778 #endif 779 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 780 781 *coneOrientation = &mesh->coneOrientations[off]; 782 PetscFunctionReturn(0); 783 } 784 785 #undef __FUNCT__ 786 #define __FUNCT__ "DMPlexSetConeOrientation" 787 /*@ 788 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 789 790 Not collective 791 792 Input Parameters: 793 + mesh - The DMPlex 794 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 795 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 796 integer giving the prescription for cone traversal. If it is negative, the cone is 797 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 798 the index of the cone point on which to start. 799 800 Output Parameter: 801 802 Note: 803 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 804 805 Level: beginner 806 807 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 808 @*/ 809 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 810 { 811 DM_Plex *mesh = (DM_Plex*) dm->data; 812 PetscInt pStart, pEnd; 813 PetscInt dof, off, c; 814 PetscErrorCode ierr; 815 816 PetscFunctionBegin; 817 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 818 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 819 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 820 if (dof) PetscValidPointer(coneOrientation, 3); 821 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 822 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 823 for (c = 0; c < dof; ++c) { 824 PetscInt cdof, o = coneOrientation[c]; 825 826 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 827 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 828 mesh->coneOrientations[off+c] = o; 829 } 830 PetscFunctionReturn(0); 831 } 832 833 #undef __FUNCT__ 834 #define __FUNCT__ "DMPlexInsertCone" 835 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 836 { 837 DM_Plex *mesh = (DM_Plex*) dm->data; 838 PetscInt pStart, pEnd; 839 PetscInt dof, off; 840 PetscErrorCode ierr; 841 842 PetscFunctionBegin; 843 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 844 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 845 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 846 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 847 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 848 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 849 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 850 mesh->cones[off+conePos] = conePoint; 851 PetscFunctionReturn(0); 852 } 853 854 #undef __FUNCT__ 855 #define __FUNCT__ "DMPlexInsertConeOrientation" 856 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 857 { 858 DM_Plex *mesh = (DM_Plex*) dm->data; 859 PetscInt pStart, pEnd; 860 PetscInt dof, off; 861 PetscErrorCode ierr; 862 863 PetscFunctionBegin; 864 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 865 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 866 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 867 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 868 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 869 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 870 mesh->coneOrientations[off+conePos] = coneOrientation; 871 PetscFunctionReturn(0); 872 } 873 874 #undef __FUNCT__ 875 #define __FUNCT__ "DMPlexGetSupportSize" 876 /*@ 877 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 878 879 Not collective 880 881 Input Parameters: 882 + mesh - The DMPlex 883 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 884 885 Output Parameter: 886 . size - The support size for point p 887 888 Level: beginner 889 890 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 891 @*/ 892 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 893 { 894 DM_Plex *mesh = (DM_Plex*) dm->data; 895 PetscErrorCode ierr; 896 897 PetscFunctionBegin; 898 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 899 PetscValidPointer(size, 3); 900 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 901 PetscFunctionReturn(0); 902 } 903 904 #undef __FUNCT__ 905 #define __FUNCT__ "DMPlexSetSupportSize" 906 /*@ 907 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 908 909 Not collective 910 911 Input Parameters: 912 + mesh - The DMPlex 913 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 914 - size - The support size for point p 915 916 Output Parameter: 917 918 Note: 919 This should be called after DMPlexSetChart(). 920 921 Level: beginner 922 923 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 924 @*/ 925 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 926 { 927 DM_Plex *mesh = (DM_Plex*) dm->data; 928 PetscErrorCode ierr; 929 930 PetscFunctionBegin; 931 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 932 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 933 934 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 935 PetscFunctionReturn(0); 936 } 937 938 #undef __FUNCT__ 939 #define __FUNCT__ "DMPlexGetSupport" 940 /*@C 941 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 942 943 Not collective 944 945 Input Parameters: 946 + mesh - The DMPlex 947 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 948 949 Output Parameter: 950 . support - An array of points which are on the out-edges for point p 951 952 Level: beginner 953 954 Fortran Notes: 955 Since it returns an array, this routine is only available in Fortran 90, and you must 956 include petsc.h90 in your code. 957 958 You must also call DMPlexRestoreSupport() after you finish using the returned array. 959 960 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 961 @*/ 962 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 963 { 964 DM_Plex *mesh = (DM_Plex*) dm->data; 965 PetscInt off; 966 PetscErrorCode ierr; 967 968 PetscFunctionBegin; 969 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 970 PetscValidPointer(support, 3); 971 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 972 *support = &mesh->supports[off]; 973 PetscFunctionReturn(0); 974 } 975 976 #undef __FUNCT__ 977 #define __FUNCT__ "DMPlexSetSupport" 978 /*@ 979 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 980 981 Not collective 982 983 Input Parameters: 984 + mesh - The DMPlex 985 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 986 - support - An array of points which are on the in-edges for point p 987 988 Output Parameter: 989 990 Note: 991 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 992 993 Level: beginner 994 995 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 996 @*/ 997 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 998 { 999 DM_Plex *mesh = (DM_Plex*) dm->data; 1000 PetscInt pStart, pEnd; 1001 PetscInt dof, off, c; 1002 PetscErrorCode ierr; 1003 1004 PetscFunctionBegin; 1005 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1006 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1007 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1008 if (dof) PetscValidPointer(support, 3); 1009 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1010 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1011 for (c = 0; c < dof; ++c) { 1012 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1013 mesh->supports[off+c] = support[c]; 1014 } 1015 PetscFunctionReturn(0); 1016 } 1017 1018 #undef __FUNCT__ 1019 #define __FUNCT__ "DMPlexInsertSupport" 1020 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1021 { 1022 DM_Plex *mesh = (DM_Plex*) dm->data; 1023 PetscInt pStart, pEnd; 1024 PetscInt dof, off; 1025 PetscErrorCode ierr; 1026 1027 PetscFunctionBegin; 1028 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1029 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1030 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1031 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1032 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1033 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1034 if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1035 mesh->supports[off+supportPos] = supportPoint; 1036 PetscFunctionReturn(0); 1037 } 1038 1039 #undef __FUNCT__ 1040 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1041 /*@C 1042 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1043 1044 Not collective 1045 1046 Input Parameters: 1047 + mesh - The DMPlex 1048 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1049 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1050 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1051 1052 Output Parameters: 1053 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1054 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1055 1056 Note: 1057 If using internal storage (points is NULL on input), each call overwrites the last output. 1058 1059 Fortran Notes: 1060 Since it returns an array, this routine is only available in Fortran 90, and you must 1061 include petsc.h90 in your code. 1062 1063 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1064 1065 Level: beginner 1066 1067 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1068 @*/ 1069 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1070 { 1071 DM_Plex *mesh = (DM_Plex*) dm->data; 1072 PetscInt *closure, *fifo; 1073 const PetscInt *tmp = NULL, *tmpO = NULL; 1074 PetscInt tmpSize, t; 1075 PetscInt depth = 0, maxSize; 1076 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1077 PetscErrorCode ierr; 1078 1079 PetscFunctionBegin; 1080 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1081 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1082 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)),depth+1); 1083 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1084 if (*points) { 1085 closure = *points; 1086 } else { 1087 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1088 } 1089 closure[0] = p; closure[1] = 0; 1090 /* This is only 1-level */ 1091 if (useCone) { 1092 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1093 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1094 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1095 } else { 1096 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1097 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1098 } 1099 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1100 const PetscInt cp = tmp[t]; 1101 const PetscInt co = tmpO ? tmpO[t] : 0; 1102 1103 closure[closureSize] = cp; 1104 closure[closureSize+1] = co; 1105 fifo[fifoSize] = cp; 1106 fifo[fifoSize+1] = co; 1107 } 1108 while (fifoSize - fifoStart) { 1109 const PetscInt q = fifo[fifoStart]; 1110 const PetscInt o = fifo[fifoStart+1]; 1111 const PetscInt rev = o >= 0 ? 0 : 1; 1112 const PetscInt off = rev ? -(o+1) : o; 1113 1114 if (useCone) { 1115 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1116 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1117 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1118 } else { 1119 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1120 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1121 tmpO = NULL; 1122 } 1123 for (t = 0; t < tmpSize; ++t) { 1124 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1125 const PetscInt cp = tmp[i]; 1126 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 1127 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 1128 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 1129 PetscInt co = tmpO ? tmpO[i] : 0; 1130 PetscInt c; 1131 1132 if (rev) { 1133 PetscInt childSize, coff; 1134 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1135 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1136 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1137 } 1138 /* Check for duplicate */ 1139 for (c = 0; c < closureSize; c += 2) { 1140 if (closure[c] == cp) break; 1141 } 1142 if (c == closureSize) { 1143 closure[closureSize] = cp; 1144 closure[closureSize+1] = co; 1145 fifo[fifoSize] = cp; 1146 fifo[fifoSize+1] = co; 1147 closureSize += 2; 1148 fifoSize += 2; 1149 } 1150 } 1151 fifoStart += 2; 1152 } 1153 if (numPoints) *numPoints = closureSize/2; 1154 if (points) *points = closure; 1155 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1156 PetscFunctionReturn(0); 1157 } 1158 1159 #undef __FUNCT__ 1160 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1161 /*@C 1162 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1163 1164 Not collective 1165 1166 Input Parameters: 1167 + mesh - The DMPlex 1168 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1169 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1170 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1171 1172 Output Parameters: 1173 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1174 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1175 1176 Note: 1177 If not using internal storage (points is not NULL on input), this call is unnecessary 1178 1179 Fortran Notes: 1180 Since it returns an array, this routine is only available in Fortran 90, and you must 1181 include petsc.h90 in your code. 1182 1183 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1184 1185 Level: beginner 1186 1187 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1188 @*/ 1189 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1190 { 1191 PetscErrorCode ierr; 1192 1193 PetscFunctionBegin; 1194 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1195 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1196 PetscFunctionReturn(0); 1197 } 1198 1199 #undef __FUNCT__ 1200 #define __FUNCT__ "DMPlexGetMaxSizes" 1201 /*@ 1202 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1203 1204 Not collective 1205 1206 Input Parameter: 1207 . mesh - The DMPlex 1208 1209 Output Parameters: 1210 + maxConeSize - The maximum number of in-edges 1211 - maxSupportSize - The maximum number of out-edges 1212 1213 Level: beginner 1214 1215 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1216 @*/ 1217 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1218 { 1219 DM_Plex *mesh = (DM_Plex*) dm->data; 1220 1221 PetscFunctionBegin; 1222 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1223 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1224 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1225 PetscFunctionReturn(0); 1226 } 1227 1228 #undef __FUNCT__ 1229 #define __FUNCT__ "DMSetUp_Plex" 1230 PetscErrorCode DMSetUp_Plex(DM dm) 1231 { 1232 DM_Plex *mesh = (DM_Plex*) dm->data; 1233 PetscInt size; 1234 PetscErrorCode ierr; 1235 1236 PetscFunctionBegin; 1237 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1238 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1239 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1240 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1241 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1242 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1243 if (mesh->maxSupportSize) { 1244 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1245 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1246 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1247 } 1248 PetscFunctionReturn(0); 1249 } 1250 1251 #undef __FUNCT__ 1252 #define __FUNCT__ "DMCreateSubDM_Plex" 1253 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1254 { 1255 PetscErrorCode ierr; 1256 1257 PetscFunctionBegin; 1258 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 1259 ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1260 PetscFunctionReturn(0); 1261 } 1262 1263 #undef __FUNCT__ 1264 #define __FUNCT__ "DMPlexSymmetrize" 1265 /*@ 1266 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1267 1268 Not collective 1269 1270 Input Parameter: 1271 . mesh - The DMPlex 1272 1273 Output Parameter: 1274 1275 Note: 1276 This should be called after all calls to DMPlexSetCone() 1277 1278 Level: beginner 1279 1280 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1281 @*/ 1282 PetscErrorCode DMPlexSymmetrize(DM dm) 1283 { 1284 DM_Plex *mesh = (DM_Plex*) dm->data; 1285 PetscInt *offsets; 1286 PetscInt supportSize; 1287 PetscInt pStart, pEnd, p; 1288 PetscErrorCode ierr; 1289 1290 PetscFunctionBegin; 1291 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1292 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1293 /* Calculate support sizes */ 1294 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1295 for (p = pStart; p < pEnd; ++p) { 1296 PetscInt dof, off, c; 1297 1298 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1299 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1300 for (c = off; c < off+dof; ++c) { 1301 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1302 } 1303 } 1304 for (p = pStart; p < pEnd; ++p) { 1305 PetscInt dof; 1306 1307 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1308 1309 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1310 } 1311 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1312 /* Calculate supports */ 1313 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1314 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1315 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1316 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1317 for (p = pStart; p < pEnd; ++p) { 1318 PetscInt dof, off, c; 1319 1320 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1321 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1322 for (c = off; c < off+dof; ++c) { 1323 const PetscInt q = mesh->cones[c]; 1324 PetscInt offS; 1325 1326 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1327 1328 mesh->supports[offS+offsets[q]] = p; 1329 ++offsets[q]; 1330 } 1331 } 1332 ierr = PetscFree(offsets);CHKERRQ(ierr); 1333 PetscFunctionReturn(0); 1334 } 1335 1336 #undef __FUNCT__ 1337 #define __FUNCT__ "DMPlexSetDepth_Private" 1338 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1339 { 1340 PetscInt d; 1341 PetscErrorCode ierr; 1342 1343 PetscFunctionBegin; 1344 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1345 if (d < 0) { 1346 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1347 const PetscInt *cone = NULL; 1348 PetscInt dCone; 1349 1350 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1351 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1352 d = dCone+1; 1353 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1354 } 1355 *depth = d; 1356 PetscFunctionReturn(0); 1357 } 1358 1359 #undef __FUNCT__ 1360 #define __FUNCT__ "DMPlexStratify" 1361 /*@ 1362 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 1363 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 1364 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 1365 the DAG. 1366 1367 Not collective 1368 1369 Input Parameter: 1370 . mesh - The DMPlex 1371 1372 Output Parameter: 1373 1374 Notes: 1375 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 1376 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 1377 1378 This should be called after all calls to DMPlexSymmetrize() 1379 1380 Level: beginner 1381 1382 .seealso: DMPlexCreate(), DMPlexSymmetrize() 1383 @*/ 1384 PetscErrorCode DMPlexStratify(DM dm) 1385 { 1386 DM_Plex *mesh = (DM_Plex*) dm->data; 1387 PetscInt pStart, pEnd, p; 1388 PetscInt numRoots = 0, numLeaves = 0; 1389 PetscErrorCode ierr; 1390 1391 PetscFunctionBegin; 1392 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1393 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1394 /* Calculate depth */ 1395 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1396 /* Initialize roots and count leaves */ 1397 for (p = pStart; p < pEnd; ++p) { 1398 PetscInt coneSize, supportSize; 1399 1400 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1401 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1402 if (!coneSize && supportSize) { 1403 ++numRoots; 1404 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 1405 } else if (!supportSize && coneSize) { 1406 ++numLeaves; 1407 } else if (!supportSize && !coneSize) { 1408 /* Isolated points */ 1409 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 1410 } 1411 } 1412 if (numRoots + numLeaves == (pEnd - pStart)) { 1413 for (p = pStart; p < pEnd; ++p) { 1414 PetscInt coneSize, supportSize; 1415 1416 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1417 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1418 if (!supportSize && coneSize) { 1419 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 1420 } 1421 } 1422 } else { 1423 /* This might be slow since lookup is not fast */ 1424 for (p = pStart; p < pEnd; ++p) { 1425 PetscInt depth; 1426 1427 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 1428 } 1429 } 1430 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1431 PetscFunctionReturn(0); 1432 } 1433 1434 #undef __FUNCT__ 1435 #define __FUNCT__ "DMPlexGetJoin" 1436 /*@C 1437 DMPlexGetJoin - Get an array for the join of the set of points 1438 1439 Not Collective 1440 1441 Input Parameters: 1442 + dm - The DMPlex object 1443 . numPoints - The number of input points for the join 1444 - points - The input points 1445 1446 Output Parameters: 1447 + numCoveredPoints - The number of points in the join 1448 - coveredPoints - The points in the join 1449 1450 Level: intermediate 1451 1452 Note: Currently, this is restricted to a single level join 1453 1454 Fortran Notes: 1455 Since it returns an array, this routine is only available in Fortran 90, and you must 1456 include petsc.h90 in your code. 1457 1458 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1459 1460 .keywords: mesh 1461 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 1462 @*/ 1463 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 1464 { 1465 DM_Plex *mesh = (DM_Plex*) dm->data; 1466 PetscInt *join[2]; 1467 PetscInt joinSize, i = 0; 1468 PetscInt dof, off, p, c, m; 1469 PetscErrorCode ierr; 1470 1471 PetscFunctionBegin; 1472 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1473 PetscValidPointer(points, 2); 1474 PetscValidPointer(numCoveredPoints, 3); 1475 PetscValidPointer(coveredPoints, 4); 1476 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 1477 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 1478 /* Copy in support of first point */ 1479 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 1480 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 1481 for (joinSize = 0; joinSize < dof; ++joinSize) { 1482 join[i][joinSize] = mesh->supports[off+joinSize]; 1483 } 1484 /* Check each successive support */ 1485 for (p = 1; p < numPoints; ++p) { 1486 PetscInt newJoinSize = 0; 1487 1488 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 1489 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 1490 for (c = 0; c < dof; ++c) { 1491 const PetscInt point = mesh->supports[off+c]; 1492 1493 for (m = 0; m < joinSize; ++m) { 1494 if (point == join[i][m]) { 1495 join[1-i][newJoinSize++] = point; 1496 break; 1497 } 1498 } 1499 } 1500 joinSize = newJoinSize; 1501 i = 1-i; 1502 } 1503 *numCoveredPoints = joinSize; 1504 *coveredPoints = join[i]; 1505 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 1506 PetscFunctionReturn(0); 1507 } 1508 1509 #undef __FUNCT__ 1510 #define __FUNCT__ "DMPlexRestoreJoin" 1511 /*@C 1512 DMPlexRestoreJoin - Restore an array for the join of the set of points 1513 1514 Not Collective 1515 1516 Input Parameters: 1517 + dm - The DMPlex object 1518 . numPoints - The number of input points for the join 1519 - points - The input points 1520 1521 Output Parameters: 1522 + numCoveredPoints - The number of points in the join 1523 - coveredPoints - The points in the join 1524 1525 Fortran Notes: 1526 Since it returns an array, this routine is only available in Fortran 90, and you must 1527 include petsc.h90 in your code. 1528 1529 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1530 1531 Level: intermediate 1532 1533 .keywords: mesh 1534 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 1535 @*/ 1536 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 1537 { 1538 PetscErrorCode ierr; 1539 1540 PetscFunctionBegin; 1541 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1542 PetscValidPointer(coveredPoints, 4); 1543 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 1544 PetscFunctionReturn(0); 1545 } 1546 1547 #undef __FUNCT__ 1548 #define __FUNCT__ "DMPlexGetFullJoin" 1549 /*@C 1550 DMPlexGetFullJoin - Get an array for the join of the set of points 1551 1552 Not Collective 1553 1554 Input Parameters: 1555 + dm - The DMPlex object 1556 . numPoints - The number of input points for the join 1557 - points - The input points 1558 1559 Output Parameters: 1560 + numCoveredPoints - The number of points in the join 1561 - coveredPoints - The points in the join 1562 1563 Fortran Notes: 1564 Since it returns an array, this routine is only available in Fortran 90, and you must 1565 include petsc.h90 in your code. 1566 1567 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1568 1569 Level: intermediate 1570 1571 .keywords: mesh 1572 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 1573 @*/ 1574 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 1575 { 1576 DM_Plex *mesh = (DM_Plex*) dm->data; 1577 PetscInt *offsets, **closures; 1578 PetscInt *join[2]; 1579 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 1580 PetscInt p, d, c, m; 1581 PetscErrorCode ierr; 1582 1583 PetscFunctionBegin; 1584 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1585 PetscValidPointer(points, 2); 1586 PetscValidPointer(numCoveredPoints, 3); 1587 PetscValidPointer(coveredPoints, 4); 1588 1589 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1590 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 1591 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 1592 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 1593 maxSize = PetscPowInt(mesh->maxSupportSize,depth+1); 1594 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 1595 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 1596 1597 for (p = 0; p < numPoints; ++p) { 1598 PetscInt closureSize; 1599 1600 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 1601 1602 offsets[p*(depth+2)+0] = 0; 1603 for (d = 0; d < depth+1; ++d) { 1604 PetscInt pStart, pEnd, i; 1605 1606 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1607 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 1608 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 1609 offsets[p*(depth+2)+d+1] = i; 1610 break; 1611 } 1612 } 1613 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 1614 } 1615 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 1616 } 1617 for (d = 0; d < depth+1; ++d) { 1618 PetscInt dof; 1619 1620 /* Copy in support of first point */ 1621 dof = offsets[d+1] - offsets[d]; 1622 for (joinSize = 0; joinSize < dof; ++joinSize) { 1623 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 1624 } 1625 /* Check each successive cone */ 1626 for (p = 1; p < numPoints && joinSize; ++p) { 1627 PetscInt newJoinSize = 0; 1628 1629 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 1630 for (c = 0; c < dof; ++c) { 1631 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 1632 1633 for (m = 0; m < joinSize; ++m) { 1634 if (point == join[i][m]) { 1635 join[1-i][newJoinSize++] = point; 1636 break; 1637 } 1638 } 1639 } 1640 joinSize = newJoinSize; 1641 i = 1-i; 1642 } 1643 if (joinSize) break; 1644 } 1645 *numCoveredPoints = joinSize; 1646 *coveredPoints = join[i]; 1647 for (p = 0; p < numPoints; ++p) { 1648 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 1649 } 1650 ierr = PetscFree(closures);CHKERRQ(ierr); 1651 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 1652 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 1653 PetscFunctionReturn(0); 1654 } 1655 1656 #undef __FUNCT__ 1657 #define __FUNCT__ "DMPlexGetMeet" 1658 /*@C 1659 DMPlexGetMeet - Get an array for the meet of the set of points 1660 1661 Not Collective 1662 1663 Input Parameters: 1664 + dm - The DMPlex object 1665 . numPoints - The number of input points for the meet 1666 - points - The input points 1667 1668 Output Parameters: 1669 + numCoveredPoints - The number of points in the meet 1670 - coveredPoints - The points in the meet 1671 1672 Level: intermediate 1673 1674 Note: Currently, this is restricted to a single level meet 1675 1676 Fortran Notes: 1677 Since it returns an array, this routine is only available in Fortran 90, and you must 1678 include petsc.h90 in your code. 1679 1680 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1681 1682 .keywords: mesh 1683 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 1684 @*/ 1685 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 1686 { 1687 DM_Plex *mesh = (DM_Plex*) dm->data; 1688 PetscInt *meet[2]; 1689 PetscInt meetSize, i = 0; 1690 PetscInt dof, off, p, c, m; 1691 PetscErrorCode ierr; 1692 1693 PetscFunctionBegin; 1694 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1695 PetscValidPointer(points, 2); 1696 PetscValidPointer(numCoveringPoints, 3); 1697 PetscValidPointer(coveringPoints, 4); 1698 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 1699 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 1700 /* Copy in cone of first point */ 1701 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 1702 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 1703 for (meetSize = 0; meetSize < dof; ++meetSize) { 1704 meet[i][meetSize] = mesh->cones[off+meetSize]; 1705 } 1706 /* Check each successive cone */ 1707 for (p = 1; p < numPoints; ++p) { 1708 PetscInt newMeetSize = 0; 1709 1710 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 1711 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 1712 for (c = 0; c < dof; ++c) { 1713 const PetscInt point = mesh->cones[off+c]; 1714 1715 for (m = 0; m < meetSize; ++m) { 1716 if (point == meet[i][m]) { 1717 meet[1-i][newMeetSize++] = point; 1718 break; 1719 } 1720 } 1721 } 1722 meetSize = newMeetSize; 1723 i = 1-i; 1724 } 1725 *numCoveringPoints = meetSize; 1726 *coveringPoints = meet[i]; 1727 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 1728 PetscFunctionReturn(0); 1729 } 1730 1731 #undef __FUNCT__ 1732 #define __FUNCT__ "DMPlexRestoreMeet" 1733 /*@C 1734 DMPlexRestoreMeet - Restore an array for the meet of the set of points 1735 1736 Not Collective 1737 1738 Input Parameters: 1739 + dm - The DMPlex object 1740 . numPoints - The number of input points for the meet 1741 - points - The input points 1742 1743 Output Parameters: 1744 + numCoveredPoints - The number of points in the meet 1745 - coveredPoints - The points in the meet 1746 1747 Level: intermediate 1748 1749 Fortran Notes: 1750 Since it returns an array, this routine is only available in Fortran 90, and you must 1751 include petsc.h90 in your code. 1752 1753 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1754 1755 .keywords: mesh 1756 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 1757 @*/ 1758 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 1759 { 1760 PetscErrorCode ierr; 1761 1762 PetscFunctionBegin; 1763 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1764 PetscValidPointer(coveredPoints, 4); 1765 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 1766 PetscFunctionReturn(0); 1767 } 1768 1769 #undef __FUNCT__ 1770 #define __FUNCT__ "DMPlexGetFullMeet" 1771 /*@C 1772 DMPlexGetFullMeet - Get an array for the meet of the set of points 1773 1774 Not Collective 1775 1776 Input Parameters: 1777 + dm - The DMPlex object 1778 . numPoints - The number of input points for the meet 1779 - points - The input points 1780 1781 Output Parameters: 1782 + numCoveredPoints - The number of points in the meet 1783 - coveredPoints - The points in the meet 1784 1785 Level: intermediate 1786 1787 Fortran Notes: 1788 Since it returns an array, this routine is only available in Fortran 90, and you must 1789 include petsc.h90 in your code. 1790 1791 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1792 1793 .keywords: mesh 1794 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 1795 @*/ 1796 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 1797 { 1798 DM_Plex *mesh = (DM_Plex*) dm->data; 1799 PetscInt *offsets, **closures; 1800 PetscInt *meet[2]; 1801 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 1802 PetscInt p, h, c, m; 1803 PetscErrorCode ierr; 1804 1805 PetscFunctionBegin; 1806 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1807 PetscValidPointer(points, 2); 1808 PetscValidPointer(numCoveredPoints, 3); 1809 PetscValidPointer(coveredPoints, 4); 1810 1811 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 1812 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 1813 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 1814 maxSize = PetscPowInt(mesh->maxConeSize,height+1); 1815 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 1816 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 1817 1818 for (p = 0; p < numPoints; ++p) { 1819 PetscInt closureSize; 1820 1821 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 1822 1823 offsets[p*(height+2)+0] = 0; 1824 for (h = 0; h < height+1; ++h) { 1825 PetscInt pStart, pEnd, i; 1826 1827 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 1828 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 1829 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 1830 offsets[p*(height+2)+h+1] = i; 1831 break; 1832 } 1833 } 1834 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 1835 } 1836 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 1837 } 1838 for (h = 0; h < height+1; ++h) { 1839 PetscInt dof; 1840 1841 /* Copy in cone of first point */ 1842 dof = offsets[h+1] - offsets[h]; 1843 for (meetSize = 0; meetSize < dof; ++meetSize) { 1844 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 1845 } 1846 /* Check each successive cone */ 1847 for (p = 1; p < numPoints && meetSize; ++p) { 1848 PetscInt newMeetSize = 0; 1849 1850 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 1851 for (c = 0; c < dof; ++c) { 1852 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 1853 1854 for (m = 0; m < meetSize; ++m) { 1855 if (point == meet[i][m]) { 1856 meet[1-i][newMeetSize++] = point; 1857 break; 1858 } 1859 } 1860 } 1861 meetSize = newMeetSize; 1862 i = 1-i; 1863 } 1864 if (meetSize) break; 1865 } 1866 *numCoveredPoints = meetSize; 1867 *coveredPoints = meet[i]; 1868 for (p = 0; p < numPoints; ++p) { 1869 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 1870 } 1871 ierr = PetscFree(closures);CHKERRQ(ierr); 1872 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 1873 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 1874 PetscFunctionReturn(0); 1875 } 1876 1877 #undef __FUNCT__ 1878 #define __FUNCT__ "DMPlexGetNumFaceVertices" 1879 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 1880 { 1881 MPI_Comm comm; 1882 PetscErrorCode ierr; 1883 1884 PetscFunctionBegin; 1885 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1886 PetscValidPointer(numFaceVertices,3); 1887 switch (cellDim) { 1888 case 0: 1889 *numFaceVertices = 0; 1890 break; 1891 case 1: 1892 *numFaceVertices = 1; 1893 break; 1894 case 2: 1895 switch (numCorners) { 1896 case 3: /* triangle */ 1897 *numFaceVertices = 2; /* Edge has 2 vertices */ 1898 break; 1899 case 4: /* quadrilateral */ 1900 *numFaceVertices = 2; /* Edge has 2 vertices */ 1901 break; 1902 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 1903 *numFaceVertices = 3; /* Edge has 3 vertices */ 1904 break; 1905 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 1906 *numFaceVertices = 3; /* Edge has 3 vertices */ 1907 break; 1908 default: 1909 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 1910 } 1911 break; 1912 case 3: 1913 switch (numCorners) { 1914 case 4: /* tetradehdron */ 1915 *numFaceVertices = 3; /* Face has 3 vertices */ 1916 break; 1917 case 6: /* tet cohesive cells */ 1918 *numFaceVertices = 4; /* Face has 4 vertices */ 1919 break; 1920 case 8: /* hexahedron */ 1921 *numFaceVertices = 4; /* Face has 4 vertices */ 1922 break; 1923 case 9: /* tet cohesive Lagrange cells */ 1924 *numFaceVertices = 6; /* Face has 6 vertices */ 1925 break; 1926 case 10: /* quadratic tetrahedron */ 1927 *numFaceVertices = 6; /* Face has 6 vertices */ 1928 break; 1929 case 12: /* hex cohesive Lagrange cells */ 1930 *numFaceVertices = 6; /* Face has 6 vertices */ 1931 break; 1932 case 18: /* quadratic tet cohesive Lagrange cells */ 1933 *numFaceVertices = 6; /* Face has 6 vertices */ 1934 break; 1935 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 1936 *numFaceVertices = 9; /* Face has 9 vertices */ 1937 break; 1938 default: 1939 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 1940 } 1941 break; 1942 default: 1943 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 1944 } 1945 PetscFunctionReturn(0); 1946 } 1947 1948 #undef __FUNCT__ 1949 #define __FUNCT__ "DMPlexOrient" 1950 /* Trys to give the mesh a consistent orientation */ 1951 PetscErrorCode DMPlexOrient(DM dm) 1952 { 1953 PetscBT seenCells, flippedCells, seenFaces; 1954 PetscInt *faceFIFO, fTop, fBottom; 1955 PetscInt dim, h, cStart, cEnd, c, fStart, fEnd, face, maxConeSize, *revcone, *revconeO; 1956 PetscErrorCode ierr; 1957 1958 PetscFunctionBegin; 1959 /* Truth Table 1960 mismatch flips do action mismatch flipA ^ flipB action 1961 F 0 flips no F F F 1962 F 1 flip yes F T T 1963 F 2 flips no T F T 1964 T 0 flips yes T T F 1965 T 1 flip no 1966 T 2 flips yes 1967 */ 1968 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1969 ierr = DMPlexGetVTKCellHeight(dm, &h);CHKERRQ(ierr); 1970 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 1971 ierr = DMPlexGetHeightStratum(dm, h+1, &fStart, &fEnd);CHKERRQ(ierr); 1972 ierr = PetscBTCreate(cEnd - cStart, &seenCells);CHKERRQ(ierr); 1973 ierr = PetscBTMemzero(cEnd - cStart, seenCells);CHKERRQ(ierr); 1974 ierr = PetscBTCreate(cEnd - cStart, &flippedCells);CHKERRQ(ierr); 1975 ierr = PetscBTMemzero(cEnd - cStart, flippedCells);CHKERRQ(ierr); 1976 ierr = PetscBTCreate(fEnd - fStart, &seenFaces);CHKERRQ(ierr); 1977 ierr = PetscBTMemzero(fEnd - fStart, seenFaces);CHKERRQ(ierr); 1978 ierr = PetscMalloc((fEnd - fStart) * sizeof(PetscInt), &faceFIFO);CHKERRQ(ierr); 1979 fTop = fBottom = 0; 1980 /* Initialize FIFO with first cell */ 1981 { 1982 const PetscInt *cone; 1983 PetscInt coneSize; 1984 1985 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 1986 ierr = DMPlexGetCone(dm, cStart, &cone);CHKERRQ(ierr); 1987 for (c = 0; c < coneSize; ++c) { 1988 faceFIFO[fBottom++] = cone[c]; 1989 ierr = PetscBTSet(seenFaces, cone[c]-fStart);CHKERRQ(ierr); 1990 } 1991 } 1992 /* Consider each face in FIFO */ 1993 while (fTop < fBottom) { 1994 const PetscInt *support, *coneA, *coneB, *coneOA, *coneOB; 1995 PetscInt supportSize, coneSizeA, coneSizeB, posA = -1, posB = -1; 1996 PetscInt seenA, flippedA, seenB, flippedB, mismatch; 1997 1998 face = faceFIFO[fTop++]; 1999 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 2000 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 2001 if (supportSize < 2) continue; 2002 if (supportSize != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Faces should separate only two cells, not %d", supportSize); 2003 seenA = PetscBTLookup(seenCells, support[0]-cStart); 2004 flippedA = PetscBTLookup(flippedCells, support[0]-cStart); 2005 seenB = PetscBTLookup(seenCells, support[1]-cStart); 2006 flippedB = PetscBTLookup(flippedCells, support[1]-cStart); 2007 2008 ierr = DMPlexGetConeSize(dm, support[0], &coneSizeA);CHKERRQ(ierr); 2009 ierr = DMPlexGetConeSize(dm, support[1], &coneSizeB);CHKERRQ(ierr); 2010 ierr = DMPlexGetCone(dm, support[0], &coneA);CHKERRQ(ierr); 2011 ierr = DMPlexGetCone(dm, support[1], &coneB);CHKERRQ(ierr); 2012 ierr = DMPlexGetConeOrientation(dm, support[0], &coneOA);CHKERRQ(ierr); 2013 ierr = DMPlexGetConeOrientation(dm, support[1], &coneOB);CHKERRQ(ierr); 2014 for (c = 0; c < coneSizeA; ++c) { 2015 if (!PetscBTLookup(seenFaces, coneA[c]-fStart)) { 2016 faceFIFO[fBottom++] = coneA[c]; 2017 ierr = PetscBTSet(seenFaces, coneA[c]-fStart);CHKERRQ(ierr); 2018 } 2019 if (coneA[c] == face) posA = c; 2020 if (fBottom > fEnd-fStart) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face %d was pushed exceeding capacity %d > %d", coneA[c], fBottom, fEnd-fStart); 2021 } 2022 if (posA < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d could not be located in cell %d", face, support[0]); 2023 for (c = 0; c < coneSizeB; ++c) { 2024 if (!PetscBTLookup(seenFaces, coneB[c]-fStart)) { 2025 faceFIFO[fBottom++] = coneB[c]; 2026 ierr = PetscBTSet(seenFaces, coneB[c]-fStart);CHKERRQ(ierr); 2027 } 2028 if (coneB[c] == face) posB = c; 2029 if (fBottom > fEnd-fStart) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face %d was pushed exceeding capacity %d > %d", coneA[c], fBottom, fEnd-fStart); 2030 } 2031 if (posB < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d could not be located in cell %d", face, support[1]); 2032 2033 if (dim == 1) { 2034 mismatch = posA == posB; 2035 } else { 2036 mismatch = coneOA[posA] == coneOB[posB]; 2037 } 2038 2039 if (mismatch ^ (flippedA ^ flippedB)) { 2040 if (seenA && seenB) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Previously seen cells %d and %d do not match: Fault mesh is non-orientable", support[0], support[1]); 2041 if (!seenA && !flippedA) { 2042 ierr = PetscBTSet(flippedCells, support[0]-cStart);CHKERRQ(ierr); 2043 } else if (!seenB && !flippedB) { 2044 ierr = PetscBTSet(flippedCells, support[1]-cStart);CHKERRQ(ierr); 2045 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent mesh orientation: Fault mesh is non-orientable"); 2046 } else if (flippedA && flippedB) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Attempt to flip already flipped cell: Fault mesh is non-orientable"); 2047 ierr = PetscBTSet(seenCells, support[0]-cStart);CHKERRQ(ierr); 2048 ierr = PetscBTSet(seenCells, support[1]-cStart);CHKERRQ(ierr); 2049 } 2050 2051 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, NULL);CHKERRQ(ierr); 2052 ierr = DMGetWorkArray(dm, maxConeSize, PETSC_INT, &revcone);CHKERRQ(ierr); 2053 ierr = DMGetWorkArray(dm, maxConeSize, PETSC_INT, &revconeO);CHKERRQ(ierr); 2054 for (c = cStart; c < cEnd; ++c) { 2055 const PetscInt *cone, *coneO; 2056 PetscInt coneSize, faceSize, cp; 2057 2058 if (!PetscBTLookup(flippedCells, c-cStart)) continue; 2059 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 2060 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 2061 ierr = DMPlexGetConeOrientation(dm, c, &coneO);CHKERRQ(ierr); 2062 for (cp = 0; cp < coneSize; ++cp) { 2063 const PetscInt rcp = coneSize-cp-1; 2064 2065 ierr = DMPlexGetConeSize(dm, cone[rcp], &faceSize);CHKERRQ(ierr); 2066 revcone[cp] = cone[rcp]; 2067 revconeO[cp] = coneO[rcp] >= 0 ? -(faceSize-coneO[rcp]) : faceSize+coneO[rcp]; 2068 } 2069 ierr = DMPlexSetCone(dm, c, revcone);CHKERRQ(ierr); 2070 ierr = DMPlexSetConeOrientation(dm, c, revconeO);CHKERRQ(ierr); 2071 } 2072 ierr = DMRestoreWorkArray(dm, maxConeSize, PETSC_INT, &revcone);CHKERRQ(ierr); 2073 ierr = DMRestoreWorkArray(dm, maxConeSize, PETSC_INT, &revconeO);CHKERRQ(ierr); 2074 ierr = PetscBTDestroy(&seenCells);CHKERRQ(ierr); 2075 ierr = PetscBTDestroy(&flippedCells);CHKERRQ(ierr); 2076 ierr = PetscBTDestroy(&seenFaces);CHKERRQ(ierr); 2077 ierr = PetscFree(faceFIFO);CHKERRQ(ierr); 2078 PetscFunctionReturn(0); 2079 } 2080 2081 #undef __FUNCT__ 2082 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Internal" 2083 static PetscErrorCode DMPlexGetAdjacencySingleLevel_Internal(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 2084 { 2085 const PetscInt *support = NULL; 2086 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 2087 PetscErrorCode ierr; 2088 2089 PetscFunctionBegin; 2090 if (useClosure) { 2091 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 2092 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 2093 for (s = 0; s < supportSize; ++s) { 2094 const PetscInt *cone = NULL; 2095 PetscInt coneSize, c, q; 2096 2097 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 2098 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 2099 for (c = 0; c < coneSize; ++c) { 2100 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 2101 if (cone[c] == adj[q]) break; 2102 } 2103 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 2104 } 2105 } 2106 } else { 2107 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2108 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 2109 for (s = 0; s < supportSize; ++s) { 2110 const PetscInt *cone = NULL; 2111 PetscInt coneSize, c, q; 2112 2113 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 2114 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 2115 for (c = 0; c < coneSize; ++c) { 2116 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 2117 if (cone[c] == adj[q]) break; 2118 } 2119 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 2120 } 2121 } 2122 } 2123 *adjSize = numAdj; 2124 PetscFunctionReturn(0); 2125 } 2126 2127 #undef __FUNCT__ 2128 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2129 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2130 { 2131 const PetscInt maxFaceCases = 30; 2132 PetscInt numFaceCases = 0; 2133 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2134 PetscInt *off, *adj; 2135 PetscInt *neighborCells, *tmpClosure; 2136 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2137 PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 2138 PetscErrorCode ierr; 2139 2140 PetscFunctionBegin; 2141 /* For parallel partitioning, I think you have to communicate supports */ 2142 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2143 cellDim = dim - cellHeight; 2144 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2145 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 2146 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2147 if (cEnd - cStart == 0) { 2148 if (numVertices) *numVertices = 0; 2149 if (offsets) *offsets = NULL; 2150 if (adjacency) *adjacency = NULL; 2151 PetscFunctionReturn(0); 2152 } 2153 numCells = cEnd - cStart; 2154 faceDepth = depth - cellHeight; 2155 /* Setup face recognition */ 2156 if (faceDepth == 1) { 2157 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 */ 2158 2159 for (c = cStart; c < cEnd; ++c) { 2160 PetscInt corners; 2161 2162 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2163 if (!cornersSeen[corners]) { 2164 PetscInt nFV; 2165 2166 if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2167 cornersSeen[corners] = 1; 2168 2169 ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 2170 2171 numFaceVertices[numFaceCases++] = nFV; 2172 } 2173 } 2174 } 2175 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth+1),PetscPowInt(maxSupportSize,depth+1)); 2176 maxNeighbors = PetscPowInt(maxConeSize,depth+1)*PetscPowInt(maxSupportSize,depth+1); 2177 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2178 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2179 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2180 /* Count neighboring cells */ 2181 for (cell = cStart; cell < cEnd; ++cell) { 2182 PetscInt numNeighbors = maxNeighbors, n; 2183 2184 ierr = DMPlexGetAdjacencySingleLevel_Internal(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2185 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2186 for (n = 0; n < numNeighbors; ++n) { 2187 PetscInt cellPair[2]; 2188 PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 2189 PetscInt meetSize = 0; 2190 const PetscInt *meet = NULL; 2191 2192 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2193 if (cellPair[0] == cellPair[1]) continue; 2194 if (!found) { 2195 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2196 if (meetSize) { 2197 PetscInt f; 2198 2199 for (f = 0; f < numFaceCases; ++f) { 2200 if (numFaceVertices[f] == meetSize) { 2201 found = PETSC_TRUE; 2202 break; 2203 } 2204 } 2205 } 2206 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2207 } 2208 if (found) ++off[cell-cStart+1]; 2209 } 2210 } 2211 /* Prefix sum */ 2212 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2213 2214 if (adjacency) { 2215 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2216 /* Get neighboring cells */ 2217 for (cell = cStart; cell < cEnd; ++cell) { 2218 PetscInt numNeighbors = maxNeighbors, n; 2219 PetscInt cellOffset = 0; 2220 2221 ierr = DMPlexGetAdjacencySingleLevel_Internal(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2222 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2223 for (n = 0; n < numNeighbors; ++n) { 2224 PetscInt cellPair[2]; 2225 PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 2226 PetscInt meetSize = 0; 2227 const PetscInt *meet = NULL; 2228 2229 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2230 if (cellPair[0] == cellPair[1]) continue; 2231 if (!found) { 2232 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2233 if (meetSize) { 2234 PetscInt f; 2235 2236 for (f = 0; f < numFaceCases; ++f) { 2237 if (numFaceVertices[f] == meetSize) { 2238 found = PETSC_TRUE; 2239 break; 2240 } 2241 } 2242 } 2243 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2244 } 2245 if (found) { 2246 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2247 ++cellOffset; 2248 } 2249 } 2250 } 2251 } 2252 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2253 if (numVertices) *numVertices = numCells; 2254 if (offsets) *offsets = off; 2255 if (adjacency) *adjacency = adj; 2256 PetscFunctionReturn(0); 2257 } 2258 2259 #if defined(PETSC_HAVE_CHACO) 2260 #if defined(PETSC_HAVE_UNISTD_H) 2261 #include <unistd.h> 2262 #endif 2263 /* Chaco does not have an include file */ 2264 PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2265 float *ewgts, float *x, float *y, float *z, char *outassignname, 2266 char *outfilename, short *assignment, int architecture, int ndims_tot, 2267 int mesh_dims[3], double *goal, int global_method, int local_method, 2268 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2269 2270 extern int FREE_GRAPH; 2271 2272 #undef __FUNCT__ 2273 #define __FUNCT__ "DMPlexPartition_Chaco" 2274 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2275 { 2276 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2277 MPI_Comm comm; 2278 int nvtxs = numVertices; /* number of vertices in full graph */ 2279 int *vwgts = NULL; /* weights for all vertices */ 2280 float *ewgts = NULL; /* weights for all edges */ 2281 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2282 char *outassignname = NULL; /* name of assignment output file */ 2283 char *outfilename = NULL; /* output file name */ 2284 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2285 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2286 int mesh_dims[3]; /* dimensions of mesh of processors */ 2287 double *goal = NULL; /* desired set sizes for each set */ 2288 int global_method = 1; /* global partitioning algorithm */ 2289 int local_method = 1; /* local partitioning algorithm */ 2290 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2291 int vmax = 200; /* how many vertices to coarsen down to? */ 2292 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2293 double eigtol = 0.001; /* tolerance on eigenvectors */ 2294 long seed = 123636512; /* for random graph mutations */ 2295 short int *assignment; /* Output partition */ 2296 int fd_stdout, fd_pipe[2]; 2297 PetscInt *points; 2298 PetscMPIInt commSize; 2299 int i, v, p; 2300 PetscErrorCode ierr; 2301 2302 PetscFunctionBegin; 2303 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2304 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2305 if (!numVertices) { 2306 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2307 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2308 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2309 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2310 PetscFunctionReturn(0); 2311 } 2312 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2313 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2314 2315 if (global_method == INERTIAL_METHOD) { 2316 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2317 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2318 } 2319 mesh_dims[0] = commSize; 2320 mesh_dims[1] = 1; 2321 mesh_dims[2] = 1; 2322 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2323 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2324 /* TODO: check error codes for UNIX calls */ 2325 #if defined(PETSC_HAVE_UNISTD_H) 2326 { 2327 int piperet; 2328 piperet = pipe(fd_pipe); 2329 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2330 fd_stdout = dup(1); 2331 close(1); 2332 dup2(fd_pipe[1], 1); 2333 } 2334 #endif 2335 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2336 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2337 vmax, ndims, eigtol, seed); 2338 #if defined(PETSC_HAVE_UNISTD_H) 2339 { 2340 char msgLog[10000]; 2341 int count; 2342 2343 fflush(stdout); 2344 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2345 if (count < 0) count = 0; 2346 msgLog[count] = 0; 2347 close(1); 2348 dup2(fd_stdout, 1); 2349 close(fd_stdout); 2350 close(fd_pipe[0]); 2351 close(fd_pipe[1]); 2352 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2353 } 2354 #endif 2355 /* Convert to PetscSection+IS */ 2356 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2357 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2358 for (v = 0; v < nvtxs; ++v) { 2359 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2360 } 2361 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2362 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2363 for (p = 0, i = 0; p < commSize; ++p) { 2364 for (v = 0; v < nvtxs; ++v) { 2365 if (assignment[v] == p) points[i++] = v; 2366 } 2367 } 2368 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2369 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2370 if (global_method == INERTIAL_METHOD) { 2371 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2372 } 2373 ierr = PetscFree(assignment);CHKERRQ(ierr); 2374 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2375 PetscFunctionReturn(0); 2376 } 2377 #endif 2378 2379 #if defined(PETSC_HAVE_PARMETIS) 2380 #include <parmetis.h> 2381 2382 #undef __FUNCT__ 2383 #define __FUNCT__ "DMPlexPartition_ParMetis" 2384 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2385 { 2386 MPI_Comm comm; 2387 PetscInt nvtxs = numVertices; // The number of vertices in full graph 2388 PetscInt *vtxdist; // Distribution of vertices across processes 2389 PetscInt *xadj = start; // Start of edge list for each vertex 2390 PetscInt *adjncy = adjacency; // Edge lists for all vertices 2391 PetscInt *vwgt = NULL; // Vertex weights 2392 PetscInt *adjwgt = NULL; // Edge weights 2393 PetscInt wgtflag = 0; // Indicates which weights are present 2394 PetscInt numflag = 0; // Indicates initial offset (0 or 1) 2395 PetscInt ncon = 1; // The number of weights per vertex 2396 PetscInt nparts; // The number of partitions 2397 PetscReal *tpwgts; // The fraction of vertex weights assigned to each partition 2398 PetscReal *ubvec; // The balance intolerance for vertex weights 2399 PetscInt options[5]; // Options 2400 // Outputs 2401 PetscInt edgeCut; // The number of edges cut by the partition 2402 PetscInt *assignment, *points; 2403 PetscMPIInt commSize, rank, p, v, i; 2404 PetscErrorCode ierr; 2405 2406 PetscFunctionBegin; 2407 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 2408 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2409 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2410 nparts = commSize; 2411 options[0] = 0; /* Use all defaults */ 2412 /* Calculate vertex distribution */ 2413 ierr = PetscMalloc4(nparts+1,PetscInt,&vtxdist,nparts*ncon,PetscReal,&tpwgts,ncon,PetscReal,&ubvec,nvtxs,PetscInt,&assignment);CHKERRQ(ierr); 2414 vtxdist[0] = 0; 2415 ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 2416 for (p = 2; p <= nparts; ++p) { 2417 vtxdist[p] += vtxdist[p-1]; 2418 } 2419 /* Calculate weights */ 2420 for (p = 0; p < nparts; ++p) { 2421 tpwgts[p] = 1.0/nparts; 2422 } 2423 ubvec[0] = 1.05; 2424 2425 if (nparts == 1) { 2426 ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt)); 2427 } else { 2428 if (vtxdist[1] == vtxdist[nparts]) { 2429 if (!rank) { 2430 PetscStackPush("METIS_PartGraphKway"); 2431 ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment); 2432 PetscStackPop; 2433 if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 2434 } 2435 } else { 2436 PetscStackPush("ParMETIS_V3_PartKway"); 2437 ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm); 2438 PetscStackPop; 2439 if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 2440 } 2441 } 2442 /* Convert to PetscSection+IS */ 2443 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2444 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2445 for (v = 0; v < nvtxs; ++v) { 2446 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2447 } 2448 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2449 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2450 for (p = 0, i = 0; p < commSize; ++p) { 2451 for (v = 0; v < nvtxs; ++v) { 2452 if (assignment[v] == p) points[i++] = v; 2453 } 2454 } 2455 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2456 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2457 ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 2458 PetscFunctionReturn(0); 2459 } 2460 #endif 2461 2462 #undef __FUNCT__ 2463 #define __FUNCT__ "DMPlexEnlargePartition" 2464 /* Expand the partition by BFS on the adjacency graph */ 2465 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2466 { 2467 PetscHashI h; 2468 const PetscInt *points; 2469 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2470 PetscInt pStart, pEnd, part, q; 2471 PetscErrorCode ierr; 2472 2473 PetscFunctionBegin; 2474 PetscHashICreate(h); 2475 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2476 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2477 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2478 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2479 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2480 for (part = pStart; part < pEnd; ++part) { 2481 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2482 2483 PetscHashIClear(h); 2484 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2485 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2486 /* Add all existing points to h */ 2487 for (p = 0; p < numPoints; ++p) { 2488 const PetscInt point = points[off+p]; 2489 PetscHashIAdd(h, point, 1); 2490 } 2491 PetscHashISize(h, nP); 2492 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2493 /* Add all points in next BFS level */ 2494 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2495 for (p = 0; p < numPoints; ++p) { 2496 const PetscInt point = points[off+p]; 2497 PetscInt s = start[point], e = start[point+1], a; 2498 2499 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2500 } 2501 PetscHashISize(h, numNewPoints); 2502 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2503 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2504 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2505 totPoints += numNewPoints; 2506 } 2507 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2508 PetscHashIDestroy(h); 2509 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2510 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2511 for (part = pStart, q = 0; part < pEnd; ++part) { 2512 PetscInt numPoints, p; 2513 2514 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2515 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2516 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2517 } 2518 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2519 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2520 PetscFunctionReturn(0); 2521 } 2522 2523 #undef __FUNCT__ 2524 #define __FUNCT__ "DMPlexCreatePartition" 2525 /* 2526 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2527 2528 Collective on DM 2529 2530 Input Parameters: 2531 + dm - The DM 2532 . height - The height for points in the partition 2533 - enlarge - Expand each partition with neighbors 2534 2535 Output Parameters: 2536 + partSection - The PetscSection giving the division of points by partition 2537 . partition - The list of points by partition 2538 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2539 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2540 2541 Level: developer 2542 2543 .seealso DMPlexDistribute() 2544 */ 2545 PetscErrorCode DMPlexCreatePartition(DM dm, const char name[], PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2546 { 2547 char partname[1024]; 2548 PetscBool isChaco = PETSC_FALSE, isMetis = PETSC_FALSE, flg; 2549 PetscMPIInt size; 2550 PetscErrorCode ierr; 2551 2552 PetscFunctionBegin; 2553 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2554 2555 *origPartSection = NULL; 2556 *origPartition = NULL; 2557 if (size == 1) { 2558 PetscInt *points; 2559 PetscInt cStart, cEnd, c; 2560 2561 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2562 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2563 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2564 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2565 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2566 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2567 for (c = cStart; c < cEnd; ++c) points[c] = c; 2568 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2569 PetscFunctionReturn(0); 2570 } 2571 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_partitioner", partname, 1024, &flg);CHKERRQ(ierr); 2572 if (flg) name = partname; 2573 if (name) { 2574 ierr = PetscStrcmp(name, "chaco", &isChaco);CHKERRQ(ierr); 2575 ierr = PetscStrcmp(name, "metis", &isMetis);CHKERRQ(ierr); 2576 } 2577 if (height == 0) { 2578 PetscInt numVertices; 2579 PetscInt *start = NULL; 2580 PetscInt *adjacency = NULL; 2581 2582 ierr = DMPlexCreateNeighborCSR(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2583 if (!name || isChaco) { 2584 #if defined(PETSC_HAVE_CHACO) 2585 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2586 #else 2587 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 2588 #endif 2589 } else if (isMetis) { 2590 #if defined(PETSC_HAVE_PARMETIS) 2591 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2592 #endif 2593 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Unknown mesh partitioning package %s", name); 2594 if (enlarge) { 2595 *origPartSection = *partSection; 2596 *origPartition = *partition; 2597 2598 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2599 } 2600 ierr = PetscFree(start);CHKERRQ(ierr); 2601 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2602 # if 0 2603 } else if (height == 1) { 2604 /* Build the dual graph for faces and partition the hypergraph */ 2605 PetscInt numEdges; 2606 2607 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2608 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2609 destroyCSR(numEdges, start, adjacency); 2610 #endif 2611 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2612 PetscFunctionReturn(0); 2613 } 2614 2615 #undef __FUNCT__ 2616 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2617 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2618 { 2619 /* const PetscInt height = 0; */ 2620 const PetscInt *partArray; 2621 PetscInt *allPoints, *packPoints; 2622 PetscInt rStart, rEnd, rank, pStart, pEnd, newSize; 2623 PetscErrorCode ierr; 2624 PetscBT bt; 2625 PetscSegBuffer segpack,segpart; 2626 2627 PetscFunctionBegin; 2628 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2629 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2630 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2631 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2632 ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 2633 ierr = PetscBTCreate(pEnd-pStart,&bt);CHKERRQ(ierr); 2634 ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpack);CHKERRQ(ierr); 2635 ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpart);CHKERRQ(ierr); 2636 for (rank = rStart; rank < rEnd; ++rank) { 2637 PetscInt partSize = 0, numPoints, offset, p, *PETSC_RESTRICT placePoints; 2638 2639 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2640 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2641 for (p = 0; p < numPoints; ++p) { 2642 PetscInt point = partArray[offset+p], closureSize, c; 2643 PetscInt *closure = NULL; 2644 2645 /* TODO Include support for height > 0 case */ 2646 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2647 for (c=0; c<closureSize; c++) { 2648 PetscInt cpoint = closure[c*2]; 2649 if (!PetscBTLookupSet(bt,cpoint-pStart)) { 2650 PetscInt *PETSC_RESTRICT pt; 2651 partSize++; 2652 ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 2653 *pt = cpoint; 2654 } 2655 } 2656 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2657 } 2658 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 2659 ierr = PetscSegBufferGetInts(segpack,partSize,&placePoints);CHKERRQ(ierr); 2660 ierr = PetscSegBufferExtractTo(segpart,placePoints);CHKERRQ(ierr); 2661 ierr = PetscSortInt(partSize,placePoints);CHKERRQ(ierr); 2662 for (p=0; p<partSize; p++) {ierr = PetscBTClear(bt,placePoints[p]-pStart);CHKERRQ(ierr);} 2663 } 2664 ierr = PetscBTDestroy(&bt);CHKERRQ(ierr); 2665 ierr = PetscSegBufferDestroy(&segpart);CHKERRQ(ierr); 2666 2667 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 2668 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 2669 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 2670 2671 ierr = PetscSegBufferExtractInPlace(segpack,&packPoints);CHKERRQ(ierr); 2672 for (rank = rStart; rank < rEnd; ++rank) { 2673 PetscInt numPoints, offset; 2674 2675 ierr = PetscSectionGetDof(*section, rank, &numPoints);CHKERRQ(ierr); 2676 ierr = PetscSectionGetOffset(*section, rank, &offset);CHKERRQ(ierr); 2677 ierr = PetscMemcpy(&allPoints[offset], packPoints, numPoints * sizeof(PetscInt));CHKERRQ(ierr); 2678 packPoints += numPoints; 2679 } 2680 2681 ierr = PetscSegBufferDestroy(&segpack);CHKERRQ(ierr); 2682 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 2683 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2684 PetscFunctionReturn(0); 2685 } 2686 2687 #undef __FUNCT__ 2688 #define __FUNCT__ "DMPlexDistributeField" 2689 /* 2690 Input Parameters: 2691 . originalSection 2692 , originalVec 2693 2694 Output Parameters: 2695 . newSection 2696 . newVec 2697 */ 2698 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 2699 { 2700 PetscSF fieldSF; 2701 PetscInt *remoteOffsets, fieldSize; 2702 PetscScalar *originalValues, *newValues; 2703 PetscErrorCode ierr; 2704 2705 PetscFunctionBegin; 2706 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 2707 2708 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 2709 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 2710 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 2711 2712 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 2713 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 2714 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 2715 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 2716 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 2717 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 2718 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 2719 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 2720 PetscFunctionReturn(0); 2721 } 2722 2723 #undef __FUNCT__ 2724 #define __FUNCT__ "DMPlexDistribute" 2725 /*@C 2726 DMPlexDistribute - Distributes the mesh and any associated sections. 2727 2728 Not Collective 2729 2730 Input Parameter: 2731 + dm - The original DMPlex object 2732 . partitioner - The partitioning package, or NULL for the default 2733 - overlap - The overlap of partitions, 0 is the default 2734 2735 Output Parameter: 2736 . parallelMesh - The distributed DMPlex object, or NULL 2737 2738 Note: If the mesh was not distributed, the return value is NULL 2739 2740 Level: intermediate 2741 2742 .keywords: mesh, elements 2743 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 2744 @*/ 2745 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 2746 { 2747 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 2748 MPI_Comm comm; 2749 const PetscInt height = 0; 2750 PetscInt dim, numRemoteRanks; 2751 IS origCellPart, cellPart, part; 2752 PetscSection origCellPartSection, cellPartSection, partSection; 2753 PetscSFNode *remoteRanks; 2754 PetscSF partSF, pointSF, coneSF; 2755 ISLocalToGlobalMapping renumbering; 2756 PetscSection originalConeSection, newConeSection; 2757 PetscInt *remoteOffsets; 2758 PetscInt *cones, *newCones, newConesSize; 2759 PetscBool flg; 2760 PetscMPIInt rank, numProcs, p; 2761 PetscErrorCode ierr; 2762 2763 PetscFunctionBegin; 2764 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2765 PetscValidPointer(dmParallel,4); 2766 2767 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 2768 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2769 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2770 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 2771 2772 *dmParallel = NULL; 2773 if (numProcs == 1) PetscFunctionReturn(0); 2774 2775 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2776 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 2777 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 2778 ierr = DMPlexCreatePartition(dm, partitioner, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 2779 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 2780 if (!rank) numRemoteRanks = numProcs; 2781 else numRemoteRanks = 0; 2782 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 2783 for (p = 0; p < numRemoteRanks; ++p) { 2784 remoteRanks[p].rank = p; 2785 remoteRanks[p].index = 0; 2786 } 2787 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 2788 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 2789 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 2790 if (flg) { 2791 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 2792 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2793 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 2794 if (origCellPart) { 2795 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 2796 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2797 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 2798 } 2799 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 2800 } 2801 /* Close the partition over the mesh */ 2802 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 2803 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 2804 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 2805 /* Create new mesh */ 2806 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 2807 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 2808 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 2809 pmesh = (DM_Plex*) (*dmParallel)->data; 2810 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 2811 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 2812 if (flg) { 2813 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 2814 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2815 ierr = ISView(part, NULL);CHKERRQ(ierr); 2816 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 2817 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 2818 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 2819 } 2820 /* Distribute cone section */ 2821 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 2822 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 2823 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 2824 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 2825 { 2826 PetscInt pStart, pEnd, p; 2827 2828 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 2829 for (p = pStart; p < pEnd; ++p) { 2830 PetscInt coneSize; 2831 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 2832 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 2833 } 2834 } 2835 /* Communicate and renumber cones */ 2836 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 2837 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2838 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 2839 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2840 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2841 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 2842 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 2843 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 2844 if (flg) { 2845 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 2846 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2847 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 2848 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2849 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 2850 } 2851 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 2852 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 2853 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2854 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2855 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 2856 /* Create supports and stratify sieve */ 2857 { 2858 PetscInt pStart, pEnd; 2859 2860 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2861 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2862 } 2863 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 2864 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 2865 /* Distribute Coordinates */ 2866 { 2867 PetscSection originalCoordSection, newCoordSection; 2868 Vec originalCoordinates, newCoordinates; 2869 const char *name; 2870 2871 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 2872 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 2873 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 2874 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 2875 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 2876 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 2877 2878 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 2879 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 2880 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 2881 } 2882 /* Distribute labels */ 2883 { 2884 DMLabel next = mesh->labels, newNext = pmesh->labels; 2885 PetscInt numLabels = 0, l; 2886 2887 /* Bcast number of labels */ 2888 while (next) { 2889 ++numLabels; next = next->next; 2890 } 2891 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 2892 next = mesh->labels; 2893 for (l = 0; l < numLabels; ++l) { 2894 DMLabel newLabel; 2895 const PetscInt *partArray; 2896 char *name; 2897 PetscInt *stratumSizes = NULL, *points = NULL; 2898 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 2899 PetscInt nameSize, s, p; 2900 PetscBool isdepth; 2901 size_t len = 0; 2902 2903 /* Bcast name (could filter for no points) */ 2904 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 2905 nameSize = len; 2906 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 2907 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 2908 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 2909 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 2910 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 2911 if (isdepth) { /* skip because "depth" is not distributed */ 2912 ierr = PetscFree(name);CHKERRQ(ierr); 2913 if (!rank) next = next->next; 2914 continue; 2915 } 2916 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 2917 newLabel->name = name; 2918 /* Bcast numStrata (could filter for no points in stratum) */ 2919 if (!rank) newLabel->numStrata = next->numStrata; 2920 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 2921 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 2922 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 2923 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 2924 /* Bcast stratumValues (could filter for no points in stratum) */ 2925 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 2926 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 2927 /* Find size on each process and Scatter */ 2928 if (!rank) { 2929 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 2930 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 2931 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 2932 for (s = 0; s < next->numStrata; ++s) { 2933 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 2934 const PetscInt point = next->points[p]; 2935 PetscInt proc; 2936 2937 for (proc = 0; proc < numProcs; ++proc) { 2938 PetscInt dof, off, pPart; 2939 2940 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 2941 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 2942 for (pPart = off; pPart < off+dof; ++pPart) { 2943 if (partArray[pPart] == point) { 2944 ++stratumSizes[proc*next->numStrata+s]; 2945 break; 2946 } 2947 } 2948 } 2949 } 2950 } 2951 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 2952 } 2953 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 2954 /* Calculate stratumOffsets */ 2955 newLabel->stratumOffsets[0] = 0; 2956 for (s = 0; s < newLabel->numStrata; ++s) { 2957 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 2958 } 2959 /* Pack points and Scatter */ 2960 if (!rank) { 2961 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 2962 displs[0] = 0; 2963 for (p = 0; p < numProcs; ++p) { 2964 sendcnts[p] = 0; 2965 for (s = 0; s < next->numStrata; ++s) { 2966 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 2967 } 2968 offsets[p] = displs[p]; 2969 displs[p+1] = displs[p] + sendcnts[p]; 2970 } 2971 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 2972 for (s = 0; s < next->numStrata; ++s) { 2973 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 2974 const PetscInt point = next->points[p]; 2975 PetscInt proc; 2976 2977 for (proc = 0; proc < numProcs; ++proc) { 2978 PetscInt dof, off, pPart; 2979 2980 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 2981 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 2982 for (pPart = off; pPart < off+dof; ++pPart) { 2983 if (partArray[pPart] == point) { 2984 points[offsets[proc]++] = point; 2985 break; 2986 } 2987 } 2988 } 2989 } 2990 } 2991 } 2992 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 2993 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 2994 ierr = PetscFree(points);CHKERRQ(ierr); 2995 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 2996 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 2997 /* Renumber points */ 2998 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 2999 /* Sort points */ 3000 for (s = 0; s < newLabel->numStrata; ++s) { 3001 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3002 } 3003 /* Insert into list */ 3004 if (newNext) newNext->next = newLabel; 3005 else pmesh->labels = newLabel; 3006 newNext = newLabel; 3007 if (!rank) next = next->next; 3008 } 3009 } 3010 /* Cleanup Partition */ 3011 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3012 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3013 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3014 ierr = ISDestroy(&part);CHKERRQ(ierr); 3015 /* Create point SF for parallel mesh */ 3016 { 3017 const PetscInt *leaves; 3018 PetscSFNode *remotePoints, *rowners, *lowners; 3019 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3020 PetscInt pStart, pEnd; 3021 3022 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3023 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3024 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3025 for (p=0; p<numRoots; p++) { 3026 rowners[p].rank = -1; 3027 rowners[p].index = -1; 3028 } 3029 if (origCellPart) { 3030 /* Make sure cells in the original partition are not assigned to other procs */ 3031 const PetscInt *origCells; 3032 3033 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3034 for (p = 0; p < numProcs; ++p) { 3035 PetscInt dof, off, d; 3036 3037 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3038 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3039 for (d = off; d < off+dof; ++d) { 3040 rowners[origCells[d]].rank = p; 3041 } 3042 } 3043 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3044 } 3045 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3046 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3047 3048 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3049 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3050 for (p = 0; p < numLeaves; ++p) { 3051 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3052 lowners[p].rank = rank; 3053 lowners[p].index = leaves ? leaves[p] : p; 3054 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3055 lowners[p].rank = -2; 3056 lowners[p].index = -2; 3057 } 3058 } 3059 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3060 rowners[p].rank = -3; 3061 rowners[p].index = -3; 3062 } 3063 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3064 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3065 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3066 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3067 for (p = 0; p < numLeaves; ++p) { 3068 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3069 if (lowners[p].rank != rank) ++numGhostPoints; 3070 } 3071 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3072 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3073 for (p = 0, gp = 0; p < numLeaves; ++p) { 3074 if (lowners[p].rank != rank) { 3075 ghostPoints[gp] = leaves ? leaves[p] : p; 3076 remotePoints[gp].rank = lowners[p].rank; 3077 remotePoints[gp].index = lowners[p].index; 3078 ++gp; 3079 } 3080 } 3081 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3082 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3083 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3084 } 3085 /* Cleanup */ 3086 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3087 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3088 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3089 PetscFunctionReturn(0); 3090 } 3091 3092 #undef __FUNCT__ 3093 #define __FUNCT__ "DMPlexInvertCell" 3094 /*@C 3095 DMPlexInvertCell - This flips tetrahedron and hexahedron orientation since Plex stores them internally with outward normals. Other cells are left untouched. 3096 3097 Input Parameters: 3098 + numCorners - The number of vertices in a cell 3099 - cone - The incoming cone 3100 3101 Output Parameter: 3102 . cone - The inverted cone (in-place) 3103 3104 Level: developer 3105 3106 .seealso: DMPlexGenerate() 3107 @*/ 3108 PetscErrorCode DMPlexInvertCell(PetscInt dim, PetscInt numCorners, int cone[]) 3109 { 3110 int tmpc; 3111 3112 PetscFunctionBegin; 3113 if (dim != 3) PetscFunctionReturn(0); 3114 switch (numCorners) { 3115 case 4: 3116 tmpc = cone[0]; 3117 cone[0] = cone[1]; 3118 cone[1] = tmpc; 3119 break; 3120 case 8: 3121 tmpc = cone[1]; 3122 cone[1] = cone[3]; 3123 cone[3] = tmpc; 3124 break; 3125 default: break; 3126 } 3127 PetscFunctionReturn(0); 3128 } 3129 3130 #undef __FUNCT__ 3131 #define __FUNCT__ "DMPlexInvertCells_Internal" 3132 /* This is to fix the tetrahedron orientation from TetGen */ 3133 PETSC_UNUSED static PetscErrorCode DMPlexInvertCells_Internal(PetscInt dim, PetscInt numCells, PetscInt numCorners, int cells[]) 3134 { 3135 PetscInt bound = numCells*numCorners, coff; 3136 PetscErrorCode ierr; 3137 3138 PetscFunctionBegin; 3139 for (coff = 0; coff < bound; coff += numCorners) { 3140 ierr = DMPlexInvertCell(dim, numCorners, &cells[coff]);CHKERRQ(ierr); 3141 } 3142 PetscFunctionReturn(0); 3143 } 3144 3145 #if defined(PETSC_HAVE_TRIANGLE) 3146 #include <triangle.h> 3147 3148 #undef __FUNCT__ 3149 #define __FUNCT__ "InitInput_Triangle" 3150 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 3151 { 3152 PetscFunctionBegin; 3153 inputCtx->numberofpoints = 0; 3154 inputCtx->numberofpointattributes = 0; 3155 inputCtx->pointlist = NULL; 3156 inputCtx->pointattributelist = NULL; 3157 inputCtx->pointmarkerlist = NULL; 3158 inputCtx->numberofsegments = 0; 3159 inputCtx->segmentlist = NULL; 3160 inputCtx->segmentmarkerlist = NULL; 3161 inputCtx->numberoftriangleattributes = 0; 3162 inputCtx->trianglelist = NULL; 3163 inputCtx->numberofholes = 0; 3164 inputCtx->holelist = NULL; 3165 inputCtx->numberofregions = 0; 3166 inputCtx->regionlist = NULL; 3167 PetscFunctionReturn(0); 3168 } 3169 3170 #undef __FUNCT__ 3171 #define __FUNCT__ "InitOutput_Triangle" 3172 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 3173 { 3174 PetscFunctionBegin; 3175 outputCtx->numberofpoints = 0; 3176 outputCtx->pointlist = NULL; 3177 outputCtx->pointattributelist = NULL; 3178 outputCtx->pointmarkerlist = NULL; 3179 outputCtx->numberoftriangles = 0; 3180 outputCtx->trianglelist = NULL; 3181 outputCtx->triangleattributelist = NULL; 3182 outputCtx->neighborlist = NULL; 3183 outputCtx->segmentlist = NULL; 3184 outputCtx->segmentmarkerlist = NULL; 3185 outputCtx->numberofedges = 0; 3186 outputCtx->edgelist = NULL; 3187 outputCtx->edgemarkerlist = NULL; 3188 PetscFunctionReturn(0); 3189 } 3190 3191 #undef __FUNCT__ 3192 #define __FUNCT__ "FiniOutput_Triangle" 3193 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 3194 { 3195 PetscFunctionBegin; 3196 free(outputCtx->pointmarkerlist); 3197 free(outputCtx->edgelist); 3198 free(outputCtx->edgemarkerlist); 3199 free(outputCtx->trianglelist); 3200 free(outputCtx->neighborlist); 3201 PetscFunctionReturn(0); 3202 } 3203 3204 #undef __FUNCT__ 3205 #define __FUNCT__ "DMPlexGenerate_Triangle" 3206 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 3207 { 3208 MPI_Comm comm; 3209 PetscInt dim = 2; 3210 const PetscBool createConvexHull = PETSC_FALSE; 3211 const PetscBool constrained = PETSC_FALSE; 3212 struct triangulateio in; 3213 struct triangulateio out; 3214 PetscInt vStart, vEnd, v, eStart, eEnd, e; 3215 PetscMPIInt rank; 3216 PetscErrorCode ierr; 3217 3218 PetscFunctionBegin; 3219 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3220 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3221 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 3222 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 3223 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3224 3225 in.numberofpoints = vEnd - vStart; 3226 if (in.numberofpoints > 0) { 3227 PetscSection coordSection; 3228 Vec coordinates; 3229 PetscScalar *array; 3230 3231 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 3232 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 3233 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3234 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3235 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3236 for (v = vStart; v < vEnd; ++v) { 3237 const PetscInt idx = v - vStart; 3238 PetscInt off, d; 3239 3240 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3241 for (d = 0; d < dim; ++d) { 3242 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3243 } 3244 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3245 } 3246 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3247 } 3248 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 3249 in.numberofsegments = eEnd - eStart; 3250 if (in.numberofsegments > 0) { 3251 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 3252 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 3253 for (e = eStart; e < eEnd; ++e) { 3254 const PetscInt idx = e - eStart; 3255 const PetscInt *cone; 3256 3257 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 3258 3259 in.segmentlist[idx*2+0] = cone[0] - vStart; 3260 in.segmentlist[idx*2+1] = cone[1] - vStart; 3261 3262 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 3263 } 3264 } 3265 #if 0 /* Do not currently support holes */ 3266 PetscReal *holeCoords; 3267 PetscInt h, d; 3268 3269 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 3270 if (in.numberofholes > 0) { 3271 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 3272 for (h = 0; h < in.numberofholes; ++h) { 3273 for (d = 0; d < dim; ++d) { 3274 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 3275 } 3276 } 3277 } 3278 #endif 3279 if (!rank) { 3280 char args[32]; 3281 3282 /* Take away 'Q' for verbose output */ 3283 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 3284 if (createConvexHull) { 3285 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 3286 } 3287 if (constrained) { 3288 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 3289 } 3290 triangulate(args, &in, &out, NULL); 3291 } 3292 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 3293 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 3294 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 3295 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 3296 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 3297 3298 { 3299 const PetscInt numCorners = 3; 3300 const PetscInt numCells = out.numberoftriangles; 3301 const PetscInt numVertices = out.numberofpoints; 3302 const int *cells = out.trianglelist; 3303 const double *meshCoords = out.pointlist; 3304 3305 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3306 /* Set labels */ 3307 for (v = 0; v < numVertices; ++v) { 3308 if (out.pointmarkerlist[v]) { 3309 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3310 } 3311 } 3312 if (interpolate) { 3313 for (e = 0; e < out.numberofedges; e++) { 3314 if (out.edgemarkerlist[e]) { 3315 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3316 const PetscInt *edges; 3317 PetscInt numEdges; 3318 3319 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3320 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3321 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3322 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3323 } 3324 } 3325 } 3326 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3327 } 3328 #if 0 /* Do not currently support holes */ 3329 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 3330 #endif 3331 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 3332 PetscFunctionReturn(0); 3333 } 3334 3335 #undef __FUNCT__ 3336 #define __FUNCT__ "DMPlexRefine_Triangle" 3337 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 3338 { 3339 MPI_Comm comm; 3340 PetscInt dim = 2; 3341 struct triangulateio in; 3342 struct triangulateio out; 3343 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3344 PetscMPIInt rank; 3345 PetscErrorCode ierr; 3346 3347 PetscFunctionBegin; 3348 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3349 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3350 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 3351 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 3352 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3353 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3354 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3355 3356 in.numberofpoints = vEnd - vStart; 3357 if (in.numberofpoints > 0) { 3358 PetscSection coordSection; 3359 Vec coordinates; 3360 PetscScalar *array; 3361 3362 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 3363 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 3364 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3365 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3366 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3367 for (v = vStart; v < vEnd; ++v) { 3368 const PetscInt idx = v - vStart; 3369 PetscInt off, d; 3370 3371 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3372 for (d = 0; d < dim; ++d) { 3373 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3374 } 3375 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3376 } 3377 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3378 } 3379 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3380 3381 in.numberofcorners = 3; 3382 in.numberoftriangles = cEnd - cStart; 3383 3384 in.trianglearealist = (double*) maxVolumes; 3385 if (in.numberoftriangles > 0) { 3386 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 3387 for (c = cStart; c < cEnd; ++c) { 3388 const PetscInt idx = c - cStart; 3389 PetscInt *closure = NULL; 3390 PetscInt closureSize; 3391 3392 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3393 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 3394 for (v = 0; v < 3; ++v) { 3395 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 3396 } 3397 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3398 } 3399 } 3400 /* TODO: Segment markers are missing on input */ 3401 #if 0 /* Do not currently support holes */ 3402 PetscReal *holeCoords; 3403 PetscInt h, d; 3404 3405 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 3406 if (in.numberofholes > 0) { 3407 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 3408 for (h = 0; h < in.numberofholes; ++h) { 3409 for (d = 0; d < dim; ++d) { 3410 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 3411 } 3412 } 3413 } 3414 #endif 3415 if (!rank) { 3416 char args[32]; 3417 3418 /* Take away 'Q' for verbose output */ 3419 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 3420 triangulate(args, &in, &out, NULL); 3421 } 3422 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 3423 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 3424 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 3425 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 3426 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 3427 3428 { 3429 const PetscInt numCorners = 3; 3430 const PetscInt numCells = out.numberoftriangles; 3431 const PetscInt numVertices = out.numberofpoints; 3432 const int *cells = out.trianglelist; 3433 const double *meshCoords = out.pointlist; 3434 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3435 3436 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3437 /* Set labels */ 3438 for (v = 0; v < numVertices; ++v) { 3439 if (out.pointmarkerlist[v]) { 3440 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3441 } 3442 } 3443 if (interpolate) { 3444 PetscInt e; 3445 3446 for (e = 0; e < out.numberofedges; e++) { 3447 if (out.edgemarkerlist[e]) { 3448 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3449 const PetscInt *edges; 3450 PetscInt numEdges; 3451 3452 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3453 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3454 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3455 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3456 } 3457 } 3458 } 3459 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3460 } 3461 #if 0 /* Do not currently support holes */ 3462 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 3463 #endif 3464 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 3465 PetscFunctionReturn(0); 3466 } 3467 #endif 3468 3469 #if defined(PETSC_HAVE_TETGEN) 3470 #include <tetgen.h> 3471 #undef __FUNCT__ 3472 #define __FUNCT__ "DMPlexGenerate_Tetgen" 3473 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 3474 { 3475 MPI_Comm comm; 3476 const PetscInt dim = 3; 3477 ::tetgenio in; 3478 ::tetgenio out; 3479 PetscInt vStart, vEnd, v, fStart, fEnd, f; 3480 PetscMPIInt rank; 3481 PetscErrorCode ierr; 3482 3483 PetscFunctionBegin; 3484 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3485 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3486 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3487 in.numberofpoints = vEnd - vStart; 3488 if (in.numberofpoints > 0) { 3489 PetscSection coordSection; 3490 Vec coordinates; 3491 PetscScalar *array; 3492 3493 in.pointlist = new double[in.numberofpoints*dim]; 3494 in.pointmarkerlist = new int[in.numberofpoints]; 3495 3496 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3497 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3498 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3499 for (v = vStart; v < vEnd; ++v) { 3500 const PetscInt idx = v - vStart; 3501 PetscInt off, d; 3502 3503 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3504 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 3505 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3506 } 3507 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3508 } 3509 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 3510 3511 in.numberoffacets = fEnd - fStart; 3512 if (in.numberoffacets > 0) { 3513 in.facetlist = new tetgenio::facet[in.numberoffacets]; 3514 in.facetmarkerlist = new int[in.numberoffacets]; 3515 for (f = fStart; f < fEnd; ++f) { 3516 const PetscInt idx = f - fStart; 3517 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 3518 3519 in.facetlist[idx].numberofpolygons = 1; 3520 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 3521 in.facetlist[idx].numberofholes = 0; 3522 in.facetlist[idx].holelist = NULL; 3523 3524 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3525 for (p = 0; p < numPoints*2; p += 2) { 3526 const PetscInt point = points[p]; 3527 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 3528 } 3529 3530 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 3531 poly->numberofvertices = numVertices; 3532 poly->vertexlist = new int[poly->numberofvertices]; 3533 for (v = 0; v < numVertices; ++v) { 3534 const PetscInt vIdx = points[v] - vStart; 3535 poly->vertexlist[v] = vIdx; 3536 } 3537 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 3538 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3539 } 3540 } 3541 if (!rank) { 3542 char args[32]; 3543 3544 /* Take away 'Q' for verbose output */ 3545 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 3546 ::tetrahedralize(args, &in, &out); 3547 } 3548 { 3549 const PetscInt numCorners = 4; 3550 const PetscInt numCells = out.numberoftetrahedra; 3551 const PetscInt numVertices = out.numberofpoints; 3552 const double *meshCoords = out.pointlist; 3553 int *cells = out.tetrahedronlist; 3554 3555 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3556 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3557 /* Set labels */ 3558 for (v = 0; v < numVertices; ++v) { 3559 if (out.pointmarkerlist[v]) { 3560 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3561 } 3562 } 3563 if (interpolate) { 3564 PetscInt e; 3565 3566 for (e = 0; e < out.numberofedges; e++) { 3567 if (out.edgemarkerlist[e]) { 3568 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3569 const PetscInt *edges; 3570 PetscInt numEdges; 3571 3572 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3573 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3574 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3575 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3576 } 3577 } 3578 for (f = 0; f < out.numberoftrifaces; f++) { 3579 if (out.trifacemarkerlist[f]) { 3580 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 3581 const PetscInt *faces; 3582 PetscInt numFaces; 3583 3584 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3585 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3586 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 3587 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3588 } 3589 } 3590 } 3591 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3592 } 3593 PetscFunctionReturn(0); 3594 } 3595 3596 #undef __FUNCT__ 3597 #define __FUNCT__ "DMPlexRefine_Tetgen" 3598 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 3599 { 3600 MPI_Comm comm; 3601 const PetscInt dim = 3; 3602 ::tetgenio in; 3603 ::tetgenio out; 3604 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3605 PetscMPIInt rank; 3606 PetscErrorCode ierr; 3607 3608 PetscFunctionBegin; 3609 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3610 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3611 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3612 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3613 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3614 3615 in.numberofpoints = vEnd - vStart; 3616 if (in.numberofpoints > 0) { 3617 PetscSection coordSection; 3618 Vec coordinates; 3619 PetscScalar *array; 3620 3621 in.pointlist = new double[in.numberofpoints*dim]; 3622 in.pointmarkerlist = new int[in.numberofpoints]; 3623 3624 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3625 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3626 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3627 for (v = vStart; v < vEnd; ++v) { 3628 const PetscInt idx = v - vStart; 3629 PetscInt off, d; 3630 3631 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3632 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 3633 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3634 } 3635 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3636 } 3637 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3638 3639 in.numberofcorners = 4; 3640 in.numberoftetrahedra = cEnd - cStart; 3641 in.tetrahedronvolumelist = (double*) maxVolumes; 3642 if (in.numberoftetrahedra > 0) { 3643 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 3644 for (c = cStart; c < cEnd; ++c) { 3645 const PetscInt idx = c - cStart; 3646 PetscInt *closure = NULL; 3647 PetscInt closureSize; 3648 3649 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3650 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 3651 for (v = 0; v < 4; ++v) { 3652 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 3653 } 3654 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3655 } 3656 } 3657 /* TODO: Put in boundary faces with markers */ 3658 if (!rank) { 3659 char args[32]; 3660 3661 /* Take away 'Q' for verbose output */ 3662 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 3663 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 3664 ::tetrahedralize(args, &in, &out); 3665 } 3666 in.tetrahedronvolumelist = NULL; 3667 3668 { 3669 const PetscInt numCorners = 4; 3670 const PetscInt numCells = out.numberoftetrahedra; 3671 const PetscInt numVertices = out.numberofpoints; 3672 const double *meshCoords = out.pointlist; 3673 int *cells = out.tetrahedronlist; 3674 3675 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3676 3677 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3678 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3679 /* Set labels */ 3680 for (v = 0; v < numVertices; ++v) { 3681 if (out.pointmarkerlist[v]) { 3682 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3683 } 3684 } 3685 if (interpolate) { 3686 PetscInt e, f; 3687 3688 for (e = 0; e < out.numberofedges; e++) { 3689 if (out.edgemarkerlist[e]) { 3690 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3691 const PetscInt *edges; 3692 PetscInt numEdges; 3693 3694 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3695 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3696 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3697 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3698 } 3699 } 3700 for (f = 0; f < out.numberoftrifaces; f++) { 3701 if (out.trifacemarkerlist[f]) { 3702 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 3703 const PetscInt *faces; 3704 PetscInt numFaces; 3705 3706 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3707 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3708 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 3709 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3710 } 3711 } 3712 } 3713 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3714 } 3715 PetscFunctionReturn(0); 3716 } 3717 #endif 3718 3719 #if defined(PETSC_HAVE_CTETGEN) 3720 #include "ctetgen.h" 3721 3722 #undef __FUNCT__ 3723 #define __FUNCT__ "DMPlexGenerate_CTetgen" 3724 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 3725 { 3726 MPI_Comm comm; 3727 const PetscInt dim = 3; 3728 PLC *in, *out; 3729 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 3730 PetscMPIInt rank; 3731 PetscErrorCode ierr; 3732 3733 PetscFunctionBegin; 3734 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3735 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3736 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3737 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3738 ierr = PLCCreate(&in);CHKERRQ(ierr); 3739 ierr = PLCCreate(&out);CHKERRQ(ierr); 3740 3741 in->numberofpoints = vEnd - vStart; 3742 if (in->numberofpoints > 0) { 3743 PetscSection coordSection; 3744 Vec coordinates; 3745 PetscScalar *array; 3746 3747 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 3748 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 3749 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3750 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3751 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3752 for (v = vStart; v < vEnd; ++v) { 3753 const PetscInt idx = v - vStart; 3754 PetscInt off, d, m; 3755 3756 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3757 for (d = 0; d < dim; ++d) { 3758 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3759 } 3760 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 3761 3762 in->pointmarkerlist[idx] = (int) m; 3763 } 3764 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3765 } 3766 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 3767 3768 in->numberoffacets = fEnd - fStart; 3769 if (in->numberoffacets > 0) { 3770 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 3771 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 3772 for (f = fStart; f < fEnd; ++f) { 3773 const PetscInt idx = f - fStart; 3774 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 3775 polygon *poly; 3776 3777 in->facetlist[idx].numberofpolygons = 1; 3778 3779 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 3780 3781 in->facetlist[idx].numberofholes = 0; 3782 in->facetlist[idx].holelist = NULL; 3783 3784 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3785 for (p = 0; p < numPoints*2; p += 2) { 3786 const PetscInt point = points[p]; 3787 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 3788 } 3789 3790 poly = in->facetlist[idx].polygonlist; 3791 poly->numberofvertices = numVertices; 3792 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 3793 for (v = 0; v < numVertices; ++v) { 3794 const PetscInt vIdx = points[v] - vStart; 3795 poly->vertexlist[v] = vIdx; 3796 } 3797 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 3798 in->facetmarkerlist[idx] = (int) m; 3799 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3800 } 3801 } 3802 if (!rank) { 3803 TetGenOpts t; 3804 3805 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3806 t.in = boundary; /* Should go away */ 3807 t.plc = 1; 3808 t.quality = 1; 3809 t.edgesout = 1; 3810 t.zeroindex = 1; 3811 t.quiet = 1; 3812 t.verbose = verbose; 3813 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3814 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3815 } 3816 { 3817 const PetscInt numCorners = 4; 3818 const PetscInt numCells = out->numberoftetrahedra; 3819 const PetscInt numVertices = out->numberofpoints; 3820 const double *meshCoords = out->pointlist; 3821 int *cells = out->tetrahedronlist; 3822 3823 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3824 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3825 /* Set labels */ 3826 for (v = 0; v < numVertices; ++v) { 3827 if (out->pointmarkerlist[v]) { 3828 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 3829 } 3830 } 3831 if (interpolate) { 3832 PetscInt e; 3833 3834 for (e = 0; e < out->numberofedges; e++) { 3835 if (out->edgemarkerlist[e]) { 3836 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 3837 const PetscInt *edges; 3838 PetscInt numEdges; 3839 3840 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3841 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3842 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 3843 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3844 } 3845 } 3846 for (f = 0; f < out->numberoftrifaces; f++) { 3847 if (out->trifacemarkerlist[f]) { 3848 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 3849 const PetscInt *faces; 3850 PetscInt numFaces; 3851 3852 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3853 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3854 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 3855 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3856 } 3857 } 3858 } 3859 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3860 } 3861 3862 ierr = PLCDestroy(&in);CHKERRQ(ierr); 3863 ierr = PLCDestroy(&out);CHKERRQ(ierr); 3864 PetscFunctionReturn(0); 3865 } 3866 3867 #undef __FUNCT__ 3868 #define __FUNCT__ "DMPlexRefine_CTetgen" 3869 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 3870 { 3871 MPI_Comm comm; 3872 const PetscInt dim = 3; 3873 PLC *in, *out; 3874 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3875 PetscMPIInt rank; 3876 PetscErrorCode ierr; 3877 3878 PetscFunctionBegin; 3879 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3880 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3881 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3882 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3883 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3884 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3885 ierr = PLCCreate(&in);CHKERRQ(ierr); 3886 ierr = PLCCreate(&out);CHKERRQ(ierr); 3887 3888 in->numberofpoints = vEnd - vStart; 3889 if (in->numberofpoints > 0) { 3890 PetscSection coordSection; 3891 Vec coordinates; 3892 PetscScalar *array; 3893 3894 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 3895 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 3896 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3897 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3898 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3899 for (v = vStart; v < vEnd; ++v) { 3900 const PetscInt idx = v - vStart; 3901 PetscInt off, d, m; 3902 3903 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3904 for (d = 0; d < dim; ++d) { 3905 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3906 } 3907 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 3908 3909 in->pointmarkerlist[idx] = (int) m; 3910 } 3911 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3912 } 3913 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3914 3915 in->numberofcorners = 4; 3916 in->numberoftetrahedra = cEnd - cStart; 3917 in->tetrahedronvolumelist = maxVolumes; 3918 if (in->numberoftetrahedra > 0) { 3919 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 3920 for (c = cStart; c < cEnd; ++c) { 3921 const PetscInt idx = c - cStart; 3922 PetscInt *closure = NULL; 3923 PetscInt closureSize; 3924 3925 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3926 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 3927 for (v = 0; v < 4; ++v) { 3928 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 3929 } 3930 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3931 } 3932 } 3933 if (!rank) { 3934 TetGenOpts t; 3935 3936 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3937 3938 t.in = dm; /* Should go away */ 3939 t.refine = 1; 3940 t.varvolume = 1; 3941 t.quality = 1; 3942 t.edgesout = 1; 3943 t.zeroindex = 1; 3944 t.quiet = 1; 3945 t.verbose = verbose; /* Change this */ 3946 3947 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3948 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3949 } 3950 { 3951 const PetscInt numCorners = 4; 3952 const PetscInt numCells = out->numberoftetrahedra; 3953 const PetscInt numVertices = out->numberofpoints; 3954 const double *meshCoords = out->pointlist; 3955 int *cells = out->tetrahedronlist; 3956 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3957 3958 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3959 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3960 /* Set labels */ 3961 for (v = 0; v < numVertices; ++v) { 3962 if (out->pointmarkerlist[v]) { 3963 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 3964 } 3965 } 3966 if (interpolate) { 3967 PetscInt e, f; 3968 3969 for (e = 0; e < out->numberofedges; e++) { 3970 if (out->edgemarkerlist[e]) { 3971 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 3972 const PetscInt *edges; 3973 PetscInt numEdges; 3974 3975 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3976 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3977 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 3978 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3979 } 3980 } 3981 for (f = 0; f < out->numberoftrifaces; f++) { 3982 if (out->trifacemarkerlist[f]) { 3983 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 3984 const PetscInt *faces; 3985 PetscInt numFaces; 3986 3987 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3988 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3989 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 3990 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3991 } 3992 } 3993 } 3994 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3995 } 3996 ierr = PLCDestroy(&in);CHKERRQ(ierr); 3997 ierr = PLCDestroy(&out);CHKERRQ(ierr); 3998 PetscFunctionReturn(0); 3999 } 4000 #endif 4001 4002 #undef __FUNCT__ 4003 #define __FUNCT__ "DMPlexGenerate" 4004 /*@C 4005 DMPlexGenerate - Generates a mesh. 4006 4007 Not Collective 4008 4009 Input Parameters: 4010 + boundary - The DMPlex boundary object 4011 . name - The mesh generation package name 4012 - interpolate - Flag to create intermediate mesh elements 4013 4014 Output Parameter: 4015 . mesh - The DMPlex object 4016 4017 Level: intermediate 4018 4019 .keywords: mesh, elements 4020 .seealso: DMPlexCreate(), DMRefine() 4021 @*/ 4022 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 4023 { 4024 PetscInt dim; 4025 char genname[1024]; 4026 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 4027 PetscErrorCode ierr; 4028 4029 PetscFunctionBegin; 4030 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 4031 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 4032 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 4033 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 4034 if (flg) name = genname; 4035 if (name) { 4036 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 4037 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 4038 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 4039 } 4040 switch (dim) { 4041 case 1: 4042 if (!name || isTriangle) { 4043 #if defined(PETSC_HAVE_TRIANGLE) 4044 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 4045 #else 4046 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 4047 #endif 4048 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 4049 break; 4050 case 2: 4051 if (!name || isCTetgen) { 4052 #if defined(PETSC_HAVE_CTETGEN) 4053 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 4054 #else 4055 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 4056 #endif 4057 } else if (isTetgen) { 4058 #if defined(PETSC_HAVE_TETGEN) 4059 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 4060 #else 4061 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 4062 #endif 4063 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 4064 break; 4065 default: 4066 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 4067 } 4068 PetscFunctionReturn(0); 4069 } 4070 4071 typedef PetscInt CellRefiner; 4072 4073 #undef __FUNCT__ 4074 #define __FUNCT__ "GetDepthStart_Private" 4075 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 4076 { 4077 PetscFunctionBegin; 4078 if (cStart) *cStart = 0; 4079 if (vStart) *vStart = depthSize[depth]; 4080 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 4081 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 4082 PetscFunctionReturn(0); 4083 } 4084 4085 #undef __FUNCT__ 4086 #define __FUNCT__ "GetDepthEnd_Private" 4087 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 4088 { 4089 PetscFunctionBegin; 4090 if (cEnd) *cEnd = depthSize[depth]; 4091 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 4092 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 4093 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 4094 PetscFunctionReturn(0); 4095 } 4096 4097 #undef __FUNCT__ 4098 #define __FUNCT__ "CellRefinerGetSizes" 4099 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 4100 { 4101 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 4102 PetscErrorCode ierr; 4103 4104 PetscFunctionBegin; 4105 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4106 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4107 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4108 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4109 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4110 switch (refiner) { 4111 case 1: 4112 /* Simplicial 2D */ 4113 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 4114 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 4115 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 4116 break; 4117 case 3: 4118 /* Hybrid 2D */ 4119 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4120 cMax = PetscMin(cEnd, cMax); 4121 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4122 fMax = PetscMin(fEnd, fMax); 4123 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 4124 depthSize[1] = 2*(fMax - fStart) + 3*(cMax - cStart) + (fEnd - fMax) + (cEnd - cMax); /* Every interior face is split into 2 faces, 3 faces are added for each interior cell, and one in each hybrid cell */ 4125 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 4126 break; 4127 case 2: 4128 /* Hex 2D */ 4129 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 4130 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 4131 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 4132 break; 4133 default: 4134 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 4135 } 4136 PetscFunctionReturn(0); 4137 } 4138 4139 #undef __FUNCT__ 4140 #define __FUNCT__ "CellRefinerSetConeSizes" 4141 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 4142 { 4143 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 4144 PetscErrorCode ierr; 4145 4146 PetscFunctionBegin; 4147 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4148 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4149 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4150 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4151 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4152 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4153 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 4154 switch (refiner) { 4155 case 1: 4156 /* Simplicial 2D */ 4157 /* All cells have 3 faces */ 4158 for (c = cStart; c < cEnd; ++c) { 4159 for (r = 0; r < 4; ++r) { 4160 const PetscInt newp = (c - cStart)*4 + r; 4161 4162 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 4163 } 4164 } 4165 /* Split faces have 2 vertices and the same cells as the parent */ 4166 for (f = fStart; f < fEnd; ++f) { 4167 for (r = 0; r < 2; ++r) { 4168 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4169 PetscInt size; 4170 4171 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4172 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4173 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4174 } 4175 } 4176 /* Interior faces have 2 vertices and 2 cells */ 4177 for (c = cStart; c < cEnd; ++c) { 4178 for (r = 0; r < 3; ++r) { 4179 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 4180 4181 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4182 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4183 } 4184 } 4185 /* Old vertices have identical supports */ 4186 for (v = vStart; v < vEnd; ++v) { 4187 const PetscInt newp = vStartNew + (v - vStart); 4188 PetscInt size; 4189 4190 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4191 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4192 } 4193 /* Face vertices have 2 + cells*2 supports */ 4194 for (f = fStart; f < fEnd; ++f) { 4195 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4196 PetscInt size; 4197 4198 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4199 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 4200 } 4201 break; 4202 case 2: 4203 /* Hex 2D */ 4204 /* All cells have 4 faces */ 4205 for (c = cStart; c < cEnd; ++c) { 4206 for (r = 0; r < 4; ++r) { 4207 const PetscInt newp = (c - cStart)*4 + r; 4208 4209 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 4210 } 4211 } 4212 /* Split faces have 2 vertices and the same cells as the parent */ 4213 for (f = fStart; f < fEnd; ++f) { 4214 for (r = 0; r < 2; ++r) { 4215 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4216 PetscInt size; 4217 4218 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4219 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4220 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4221 } 4222 } 4223 /* Interior faces have 2 vertices and 2 cells */ 4224 for (c = cStart; c < cEnd; ++c) { 4225 for (r = 0; r < 4; ++r) { 4226 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4227 4228 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4229 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4230 } 4231 } 4232 /* Old vertices have identical supports */ 4233 for (v = vStart; v < vEnd; ++v) { 4234 const PetscInt newp = vStartNew + (v - vStart); 4235 PetscInt size; 4236 4237 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4238 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4239 } 4240 /* Face vertices have 2 + cells supports */ 4241 for (f = fStart; f < fEnd; ++f) { 4242 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4243 PetscInt size; 4244 4245 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4246 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 4247 } 4248 /* Cell vertices have 4 supports */ 4249 for (c = cStart; c < cEnd; ++c) { 4250 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4251 4252 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 4253 } 4254 break; 4255 case 3: 4256 /* Hybrid 2D */ 4257 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4258 cMax = PetscMin(cEnd, cMax); 4259 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4260 fMax = PetscMin(fEnd, fMax); 4261 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 4262 /* Interior cells have 3 faces */ 4263 for (c = cStart; c < cMax; ++c) { 4264 for (r = 0; r < 4; ++r) { 4265 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 4266 4267 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 4268 } 4269 } 4270 /* Hybrid cells have 4 faces */ 4271 for (c = cMax; c < cEnd; ++c) { 4272 for (r = 0; r < 2; ++r) { 4273 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 4274 4275 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 4276 } 4277 } 4278 /* Interior split faces have 2 vertices and the same cells as the parent */ 4279 for (f = fStart; f < fMax; ++f) { 4280 for (r = 0; r < 2; ++r) { 4281 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4282 PetscInt size; 4283 4284 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4285 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4286 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4287 } 4288 } 4289 /* Interior cell faces have 2 vertices and 2 cells */ 4290 for (c = cStart; c < cMax; ++c) { 4291 for (r = 0; r < 3; ++r) { 4292 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 4293 4294 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4295 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4296 } 4297 } 4298 /* Hybrid faces have 2 vertices and the same cells */ 4299 for (f = fMax; f < fEnd; ++f) { 4300 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 4301 PetscInt size; 4302 4303 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4304 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4305 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4306 } 4307 /* Hybrid cell faces have 2 vertices and 2 cells */ 4308 for (c = cMax; c < cEnd; ++c) { 4309 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4310 4311 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4312 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4313 } 4314 /* Old vertices have identical supports */ 4315 for (v = vStart; v < vEnd; ++v) { 4316 const PetscInt newp = vStartNew + (v - vStart); 4317 PetscInt size; 4318 4319 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4320 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4321 } 4322 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 4323 for (f = fStart; f < fMax; ++f) { 4324 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4325 const PetscInt *support; 4326 PetscInt size, newSize = 2, s; 4327 4328 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4329 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4330 for (s = 0; s < size; ++s) { 4331 if (support[s] >= cMax) newSize += 1; 4332 else newSize += 2; 4333 } 4334 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 4335 } 4336 break; 4337 default: 4338 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 4339 } 4340 PetscFunctionReturn(0); 4341 } 4342 4343 #undef __FUNCT__ 4344 #define __FUNCT__ "CellRefinerSetCones" 4345 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 4346 { 4347 PetscInt depth, cStart, cEnd, cMax, cStartNew, cEndNew, c, vStart, vEnd, vMax, vStartNew, vEndNew, v, fStart, fEnd, fMax, fStartNew, fEndNew, f, eStart, eEnd, eMax, eStartNew, eEndNew, r, p; 4348 PetscInt maxSupportSize, *supportRef; 4349 PetscErrorCode ierr; 4350 4351 PetscFunctionBegin; 4352 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4353 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4354 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4355 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4356 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4357 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4358 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 4359 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 4360 switch (refiner) { 4361 case 1: 4362 /* Simplicial 2D */ 4363 /* 4364 2 4365 |\ 4366 | \ 4367 | \ 4368 | \ 4369 | C \ 4370 | \ 4371 | \ 4372 2---1---1 4373 |\ D / \ 4374 | 2 0 \ 4375 |A \ / B \ 4376 0---0-------1 4377 */ 4378 /* All cells have 3 faces */ 4379 for (c = cStart; c < cEnd; ++c) { 4380 const PetscInt newp = cStartNew + (c - cStart)*4; 4381 const PetscInt *cone, *ornt; 4382 PetscInt coneNew[3], orntNew[3]; 4383 4384 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4385 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4386 /* A triangle */ 4387 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4388 orntNew[0] = ornt[0]; 4389 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 4390 orntNew[1] = -2; 4391 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4392 orntNew[2] = ornt[2]; 4393 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4394 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4395 #if 1 4396 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 4397 for (p = 0; p < 3; ++p) { 4398 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4399 } 4400 #endif 4401 /* B triangle */ 4402 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4403 orntNew[0] = ornt[0]; 4404 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4405 orntNew[1] = ornt[1]; 4406 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 4407 orntNew[2] = -2; 4408 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4409 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4410 #if 1 4411 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 4412 for (p = 0; p < 3; ++p) { 4413 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4414 } 4415 #endif 4416 /* C triangle */ 4417 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 4418 orntNew[0] = -2; 4419 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4420 orntNew[1] = ornt[1]; 4421 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4422 orntNew[2] = ornt[2]; 4423 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4424 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4425 #if 1 4426 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 4427 for (p = 0; p < 3; ++p) { 4428 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4429 } 4430 #endif 4431 /* D triangle */ 4432 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 4433 orntNew[0] = 0; 4434 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 4435 orntNew[1] = 0; 4436 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 4437 orntNew[2] = 0; 4438 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4439 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4440 #if 1 4441 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 4442 for (p = 0; p < 3; ++p) { 4443 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4444 } 4445 #endif 4446 } 4447 /* Split faces have 2 vertices and the same cells as the parent */ 4448 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4449 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4450 for (f = fStart; f < fEnd; ++f) { 4451 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4452 4453 for (r = 0; r < 2; ++r) { 4454 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4455 const PetscInt *cone, *support; 4456 PetscInt coneNew[2], coneSize, c, supportSize, s; 4457 4458 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4459 coneNew[0] = vStartNew + (cone[0] - vStart); 4460 coneNew[1] = vStartNew + (cone[1] - vStart); 4461 coneNew[(r+1)%2] = newv; 4462 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4463 #if 1 4464 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4465 for (p = 0; p < 2; ++p) { 4466 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 4467 } 4468 #endif 4469 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4470 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4471 for (s = 0; s < supportSize; ++s) { 4472 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4473 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4474 for (c = 0; c < coneSize; ++c) { 4475 if (cone[c] == f) break; 4476 } 4477 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 4478 } 4479 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4480 #if 1 4481 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4482 for (p = 0; p < supportSize; ++p) { 4483 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 4484 } 4485 #endif 4486 } 4487 } 4488 /* Interior faces have 2 vertices and 2 cells */ 4489 for (c = cStart; c < cEnd; ++c) { 4490 const PetscInt *cone; 4491 4492 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4493 for (r = 0; r < 3; ++r) { 4494 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 4495 PetscInt coneNew[2]; 4496 PetscInt supportNew[2]; 4497 4498 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4499 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 4500 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4501 #if 1 4502 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4503 for (p = 0; p < 2; ++p) { 4504 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 4505 } 4506 #endif 4507 supportNew[0] = (c - cStart)*4 + (r+1)%3; 4508 supportNew[1] = (c - cStart)*4 + 3; 4509 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4510 #if 1 4511 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4512 for (p = 0; p < 2; ++p) { 4513 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 4514 } 4515 #endif 4516 } 4517 } 4518 /* Old vertices have identical supports */ 4519 for (v = vStart; v < vEnd; ++v) { 4520 const PetscInt newp = vStartNew + (v - vStart); 4521 const PetscInt *support, *cone; 4522 PetscInt size, s; 4523 4524 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4525 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 4526 for (s = 0; s < size; ++s) { 4527 PetscInt r = 0; 4528 4529 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4530 if (cone[1] == v) r = 1; 4531 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 4532 } 4533 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4534 #if 1 4535 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4536 for (p = 0; p < size; ++p) { 4537 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 4538 } 4539 #endif 4540 } 4541 /* Face vertices have 2 + cells*2 supports */ 4542 for (f = fStart; f < fEnd; ++f) { 4543 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4544 const PetscInt *cone, *support; 4545 PetscInt size, s; 4546 4547 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4548 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4549 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 4550 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 4551 for (s = 0; s < size; ++s) { 4552 PetscInt r = 0; 4553 4554 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4555 if (cone[1] == f) r = 1; 4556 else if (cone[2] == f) r = 2; 4557 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 4558 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 4559 } 4560 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4561 #if 1 4562 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4563 for (p = 0; p < 2+size*2; ++p) { 4564 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 4565 } 4566 #endif 4567 } 4568 ierr = PetscFree(supportRef);CHKERRQ(ierr); 4569 break; 4570 case 2: 4571 /* Hex 2D */ 4572 /* 4573 3---------2---------2 4574 | | | 4575 | D 2 C | 4576 | | | 4577 3----3----0----1----1 4578 | | | 4579 | A 0 B | 4580 | | | 4581 0---------0---------1 4582 */ 4583 /* All cells have 4 faces */ 4584 for (c = cStart; c < cEnd; ++c) { 4585 const PetscInt newp = (c - cStart)*4; 4586 const PetscInt *cone, *ornt; 4587 PetscInt coneNew[4], orntNew[4]; 4588 4589 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4590 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4591 /* A quad */ 4592 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4593 orntNew[0] = ornt[0]; 4594 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 4595 orntNew[1] = 0; 4596 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 4597 orntNew[2] = -2; 4598 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 4599 orntNew[3] = ornt[3]; 4600 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4601 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4602 #if 1 4603 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 4604 for (p = 0; p < 4; ++p) { 4605 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4606 } 4607 #endif 4608 /* B quad */ 4609 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4610 orntNew[0] = ornt[0]; 4611 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4612 orntNew[1] = ornt[1]; 4613 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 4614 orntNew[2] = 0; 4615 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 4616 orntNew[3] = -2; 4617 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4618 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4619 #if 1 4620 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 4621 for (p = 0; p < 4; ++p) { 4622 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4623 } 4624 #endif 4625 /* C quad */ 4626 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 4627 orntNew[0] = -2; 4628 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4629 orntNew[1] = ornt[1]; 4630 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4631 orntNew[2] = ornt[2]; 4632 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 4633 orntNew[3] = 0; 4634 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4635 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4636 #if 1 4637 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 4638 for (p = 0; p < 4; ++p) { 4639 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4640 } 4641 #endif 4642 /* D quad */ 4643 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 4644 orntNew[0] = 0; 4645 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 4646 orntNew[1] = -2; 4647 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4648 orntNew[2] = ornt[2]; 4649 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 4650 orntNew[3] = ornt[3]; 4651 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4652 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4653 #if 1 4654 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 4655 for (p = 0; p < 4; ++p) { 4656 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4657 } 4658 #endif 4659 } 4660 /* Split faces have 2 vertices and the same cells as the parent */ 4661 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4662 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4663 for (f = fStart; f < fEnd; ++f) { 4664 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4665 4666 for (r = 0; r < 2; ++r) { 4667 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4668 const PetscInt *cone, *support; 4669 PetscInt coneNew[2], coneSize, c, supportSize, s; 4670 4671 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4672 coneNew[0] = vStartNew + (cone[0] - vStart); 4673 coneNew[1] = vStartNew + (cone[1] - vStart); 4674 coneNew[(r+1)%2] = newv; 4675 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4676 #if 1 4677 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4678 for (p = 0; p < 2; ++p) { 4679 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 4680 } 4681 #endif 4682 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4683 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4684 for (s = 0; s < supportSize; ++s) { 4685 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4686 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4687 for (c = 0; c < coneSize; ++c) { 4688 if (cone[c] == f) break; 4689 } 4690 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 4691 } 4692 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4693 #if 1 4694 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4695 for (p = 0; p < supportSize; ++p) { 4696 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 4697 } 4698 #endif 4699 } 4700 } 4701 /* Interior faces have 2 vertices and 2 cells */ 4702 for (c = cStart; c < cEnd; ++c) { 4703 const PetscInt *cone; 4704 PetscInt coneNew[2], supportNew[2]; 4705 4706 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4707 for (r = 0; r < 4; ++r) { 4708 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4709 4710 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4711 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4712 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4713 #if 1 4714 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4715 for (p = 0; p < 2; ++p) { 4716 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 4717 } 4718 #endif 4719 supportNew[0] = (c - cStart)*4 + r; 4720 supportNew[1] = (c - cStart)*4 + (r+1)%4; 4721 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4722 #if 1 4723 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4724 for (p = 0; p < 2; ++p) { 4725 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 4726 } 4727 #endif 4728 } 4729 } 4730 /* Old vertices have identical supports */ 4731 for (v = vStart; v < vEnd; ++v) { 4732 const PetscInt newp = vStartNew + (v - vStart); 4733 const PetscInt *support, *cone; 4734 PetscInt size, s; 4735 4736 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4737 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 4738 for (s = 0; s < size; ++s) { 4739 PetscInt r = 0; 4740 4741 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4742 if (cone[1] == v) r = 1; 4743 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 4744 } 4745 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4746 #if 1 4747 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4748 for (p = 0; p < size; ++p) { 4749 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 4750 } 4751 #endif 4752 } 4753 /* Face vertices have 2 + cells supports */ 4754 for (f = fStart; f < fEnd; ++f) { 4755 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4756 const PetscInt *cone, *support; 4757 PetscInt size, s; 4758 4759 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4760 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4761 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 4762 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 4763 for (s = 0; s < size; ++s) { 4764 PetscInt r = 0; 4765 4766 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4767 if (cone[1] == f) r = 1; 4768 else if (cone[2] == f) r = 2; 4769 else if (cone[3] == f) r = 3; 4770 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 4771 } 4772 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4773 #if 1 4774 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4775 for (p = 0; p < 2+size; ++p) { 4776 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 4777 } 4778 #endif 4779 } 4780 /* Cell vertices have 4 supports */ 4781 for (c = cStart; c < cEnd; ++c) { 4782 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4783 PetscInt supportNew[4]; 4784 4785 for (r = 0; r < 4; ++r) { 4786 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4787 } 4788 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4789 } 4790 break; 4791 case 3: 4792 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4793 cMax = PetscMin(cEnd, cMax); 4794 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4795 fMax = PetscMin(fEnd, fMax); 4796 /* Interior cells have 3 faces */ 4797 for (c = cStart; c < cMax; ++c) { 4798 const PetscInt newp = cStartNew + (c - cStart)*4; 4799 const PetscInt *cone, *ornt; 4800 PetscInt coneNew[3], orntNew[3]; 4801 4802 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4803 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4804 /* A triangle */ 4805 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4806 orntNew[0] = ornt[0]; 4807 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 4808 orntNew[1] = -2; 4809 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4810 orntNew[2] = ornt[2]; 4811 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4812 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4813 #if 1 4814 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 4815 for (p = 0; p < 3; ++p) { 4816 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4817 } 4818 #endif 4819 /* B triangle */ 4820 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4821 orntNew[0] = ornt[0]; 4822 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4823 orntNew[1] = ornt[1]; 4824 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 4825 orntNew[2] = -2; 4826 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4827 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4828 #if 1 4829 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 4830 for (p = 0; p < 3; ++p) { 4831 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4832 } 4833 #endif 4834 /* C triangle */ 4835 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 4836 orntNew[0] = -2; 4837 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4838 orntNew[1] = ornt[1]; 4839 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4840 orntNew[2] = ornt[2]; 4841 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4842 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4843 #if 1 4844 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 4845 for (p = 0; p < 3; ++p) { 4846 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4847 } 4848 #endif 4849 /* D triangle */ 4850 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 4851 orntNew[0] = 0; 4852 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 4853 orntNew[1] = 0; 4854 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 4855 orntNew[2] = 0; 4856 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4857 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4858 #if 1 4859 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 4860 for (p = 0; p < 3; ++p) { 4861 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4862 } 4863 #endif 4864 } 4865 /* 4866 2----3----3 4867 | | 4868 | B | 4869 | | 4870 0----4--- 1 4871 | | 4872 | A | 4873 | | 4874 0----2----1 4875 */ 4876 /* Hybrid cells have 4 faces */ 4877 for (c = cMax; c < cEnd; ++c) { 4878 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 4879 const PetscInt *cone, *ornt; 4880 PetscInt coneNew[4], orntNew[4]; 4881 4882 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4883 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4884 /* A quad */ 4885 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4886 orntNew[0] = ornt[0]; 4887 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4888 orntNew[1] = ornt[1]; 4889 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 4890 orntNew[2] = 0; 4891 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4892 orntNew[3] = 0; 4893 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4894 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4895 #if 1 4896 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 4897 for (p = 0; p < 4; ++p) { 4898 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4899 } 4900 #endif 4901 /* B quad */ 4902 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4903 orntNew[0] = ornt[0]; 4904 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4905 orntNew[1] = ornt[1]; 4906 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4907 orntNew[2] = 0; 4908 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 4909 orntNew[3] = 0; 4910 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4911 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4912 #if 1 4913 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 4914 for (p = 0; p < 4; ++p) { 4915 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 4916 } 4917 #endif 4918 } 4919 /* Interior split faces have 2 vertices and the same cells as the parent */ 4920 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4921 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4922 for (f = fStart; f < fMax; ++f) { 4923 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4924 4925 for (r = 0; r < 2; ++r) { 4926 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4927 const PetscInt *cone, *support; 4928 PetscInt coneNew[2], coneSize, c, supportSize, s; 4929 4930 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4931 coneNew[0] = vStartNew + (cone[0] - vStart); 4932 coneNew[1] = vStartNew + (cone[1] - vStart); 4933 coneNew[(r+1)%2] = newv; 4934 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4935 #if 1 4936 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4937 for (p = 0; p < 2; ++p) { 4938 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 4939 } 4940 #endif 4941 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4942 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4943 for (s = 0; s < supportSize; ++s) { 4944 if (support[s] >= cMax) { 4945 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 4946 } else { 4947 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4948 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4949 for (c = 0; c < coneSize; ++c) { 4950 if (cone[c] == f) break; 4951 } 4952 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 4953 } 4954 } 4955 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4956 #if 1 4957 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4958 for (p = 0; p < supportSize; ++p) { 4959 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 4960 } 4961 #endif 4962 } 4963 } 4964 /* Interior cell faces have 2 vertices and 2 cells */ 4965 for (c = cStart; c < cMax; ++c) { 4966 const PetscInt *cone; 4967 4968 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4969 for (r = 0; r < 3; ++r) { 4970 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 4971 PetscInt coneNew[2]; 4972 PetscInt supportNew[2]; 4973 4974 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4975 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 4976 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4977 #if 1 4978 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4979 for (p = 0; p < 2; ++p) { 4980 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 4981 } 4982 #endif 4983 supportNew[0] = (c - cStart)*4 + (r+1)%3; 4984 supportNew[1] = (c - cStart)*4 + 3; 4985 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4986 #if 1 4987 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4988 for (p = 0; p < 2; ++p) { 4989 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 4990 } 4991 #endif 4992 } 4993 } 4994 /* Interior hybrid faces have 2 vertices and the same cells */ 4995 for (f = fMax; f < fEnd; ++f) { 4996 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 4997 const PetscInt *cone; 4998 const PetscInt *support; 4999 PetscInt coneNew[2]; 5000 PetscInt supportNew[2]; 5001 PetscInt size, s, r; 5002 5003 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5004 coneNew[0] = vStartNew + (cone[0] - vStart); 5005 coneNew[1] = vStartNew + (cone[1] - vStart); 5006 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5007 #if 1 5008 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5009 for (p = 0; p < 2; ++p) { 5010 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5011 } 5012 #endif 5013 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5014 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5015 for (s = 0; s < size; ++s) { 5016 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5017 for (r = 0; r < 2; ++r) { 5018 if (cone[r+2] == f) break; 5019 } 5020 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 5021 } 5022 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5023 #if 1 5024 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5025 for (p = 0; p < size; ++p) { 5026 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 5027 } 5028 #endif 5029 } 5030 /* Cell hybrid faces have 2 vertices and 2 cells */ 5031 for (c = cMax; c < cEnd; ++c) { 5032 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5033 const PetscInt *cone; 5034 PetscInt coneNew[2]; 5035 PetscInt supportNew[2]; 5036 5037 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5038 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 5039 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 5040 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5041 #if 1 5042 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5043 for (p = 0; p < 2; ++p) { 5044 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5045 } 5046 #endif 5047 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 5048 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 5049 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5050 #if 1 5051 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5052 for (p = 0; p < 2; ++p) { 5053 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 5054 } 5055 #endif 5056 } 5057 /* Old vertices have identical supports */ 5058 for (v = vStart; v < vEnd; ++v) { 5059 const PetscInt newp = vStartNew + (v - vStart); 5060 const PetscInt *support, *cone; 5061 PetscInt size, s; 5062 5063 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5064 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5065 for (s = 0; s < size; ++s) { 5066 if (support[s] >= fMax) { 5067 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 5068 } else { 5069 PetscInt r = 0; 5070 5071 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5072 if (cone[1] == v) r = 1; 5073 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5074 } 5075 } 5076 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5077 #if 1 5078 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5079 for (p = 0; p < size; ++p) { 5080 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5081 } 5082 #endif 5083 } 5084 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5085 for (f = fStart; f < fMax; ++f) { 5086 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5087 const PetscInt *cone, *support; 5088 PetscInt size, newSize = 2, s; 5089 5090 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5091 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5092 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5093 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5094 for (s = 0; s < size; ++s) { 5095 PetscInt r = 0; 5096 5097 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5098 if (support[s] >= cMax) { 5099 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 5100 5101 newSize += 1; 5102 } else { 5103 if (cone[1] == f) r = 1; 5104 else if (cone[2] == f) r = 2; 5105 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5106 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 5107 5108 newSize += 2; 5109 } 5110 } 5111 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5112 #if 1 5113 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5114 for (p = 0; p < newSize; ++p) { 5115 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5116 } 5117 #endif 5118 } 5119 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5120 break; 5121 default: 5122 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5123 } 5124 PetscFunctionReturn(0); 5125 } 5126 5127 #undef __FUNCT__ 5128 #define __FUNCT__ "CellRefinerSetCoordinates" 5129 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5130 { 5131 PetscSection coordSection, coordSectionNew; 5132 Vec coordinates, coordinatesNew; 5133 PetscScalar *coords, *coordsNew; 5134 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 5135 PetscErrorCode ierr; 5136 5137 PetscFunctionBegin; 5138 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5139 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5140 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5141 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5142 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5143 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 5144 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 5145 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5146 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 5147 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 5148 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 5149 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 5150 if (fMax < 0) fMax = fEnd; 5151 switch (refiner) { 5152 case 1: 5153 case 2: 5154 case 3: 5155 /* Simplicial and Hex 2D */ 5156 /* All vertices have the dim coordinates */ 5157 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 5158 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 5159 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 5160 } 5161 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 5162 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 5163 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5164 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 5165 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 5166 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 5167 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 5168 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 5169 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 5170 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5171 /* Old vertices have the same coordinates */ 5172 for (v = vStart; v < vEnd; ++v) { 5173 const PetscInt newv = vStartNew + (v - vStart); 5174 PetscInt off, offnew, d; 5175 5176 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5177 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5178 for (d = 0; d < dim; ++d) { 5179 coordsNew[offnew+d] = coords[off+d]; 5180 } 5181 } 5182 /* Face vertices have the average of endpoint coordinates */ 5183 for (f = fStart; f < fMax; ++f) { 5184 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5185 const PetscInt *cone; 5186 PetscInt coneSize, offA, offB, offnew, d; 5187 5188 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 5189 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 5190 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5191 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5192 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5193 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5194 for (d = 0; d < dim; ++d) { 5195 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 5196 } 5197 } 5198 /* Just Hex 2D */ 5199 if (refiner == 2) { 5200 /* Cell vertices have the average of corner coordinates */ 5201 for (c = cStart; c < cEnd; ++c) { 5202 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5203 PetscInt *cone = NULL; 5204 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 5205 5206 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5207 for (p = 0; p < closureSize*2; p += 2) { 5208 const PetscInt point = cone[p]; 5209 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 5210 } 5211 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 5212 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5213 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5214 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 5215 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 5216 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5217 for (d = 0; d < dim; ++d) { 5218 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 5219 } 5220 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5221 } 5222 } 5223 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 5224 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5225 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 5226 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 5227 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 5228 break; 5229 default: 5230 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5231 } 5232 PetscFunctionReturn(0); 5233 } 5234 5235 #undef __FUNCT__ 5236 #define __FUNCT__ "DMPlexCreateProcessSF" 5237 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 5238 { 5239 PetscInt numRoots, numLeaves, l; 5240 const PetscInt *localPoints; 5241 const PetscSFNode *remotePoints; 5242 PetscInt *localPointsNew; 5243 PetscSFNode *remotePointsNew; 5244 PetscInt *ranks, *ranksNew; 5245 PetscErrorCode ierr; 5246 5247 PetscFunctionBegin; 5248 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5249 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 5250 for (l = 0; l < numLeaves; ++l) { 5251 ranks[l] = remotePoints[l].rank; 5252 } 5253 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 5254 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 5255 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 5256 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 5257 for (l = 0; l < numLeaves; ++l) { 5258 ranksNew[l] = ranks[l]; 5259 localPointsNew[l] = l; 5260 remotePointsNew[l].index = 0; 5261 remotePointsNew[l].rank = ranksNew[l]; 5262 } 5263 ierr = PetscFree(ranks);CHKERRQ(ierr); 5264 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 5265 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 5266 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 5267 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 5268 PetscFunctionReturn(0); 5269 } 5270 5271 #undef __FUNCT__ 5272 #define __FUNCT__ "CellRefinerCreateSF" 5273 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5274 { 5275 PetscSF sf, sfNew, sfProcess; 5276 IS processRanks; 5277 MPI_Datatype depthType; 5278 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 5279 const PetscInt *localPoints, *neighbors; 5280 const PetscSFNode *remotePoints; 5281 PetscInt *localPointsNew; 5282 PetscSFNode *remotePointsNew; 5283 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 5284 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 5285 PetscErrorCode ierr; 5286 5287 PetscFunctionBegin; 5288 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 5289 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5290 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5291 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5292 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5293 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5294 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5295 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5296 switch (refiner) { 5297 case 3: 5298 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5299 cMax = PetscMin(cEnd, cMax); 5300 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5301 fMax = PetscMin(fEnd, fMax); 5302 } 5303 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 5304 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 5305 /* Caculate size of new SF */ 5306 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5307 if (numRoots < 0) PetscFunctionReturn(0); 5308 for (l = 0; l < numLeaves; ++l) { 5309 const PetscInt p = localPoints[l]; 5310 5311 switch (refiner) { 5312 case 1: 5313 /* Simplicial 2D */ 5314 if ((p >= vStart) && (p < vEnd)) { 5315 /* Old vertices stay the same */ 5316 ++numLeavesNew; 5317 } else if ((p >= fStart) && (p < fEnd)) { 5318 /* Old faces add new faces and vertex */ 5319 numLeavesNew += 1 + 2; 5320 } else if ((p >= cStart) && (p < cEnd)) { 5321 /* Old cells add new cells and interior faces */ 5322 numLeavesNew += 4 + 3; 5323 } 5324 break; 5325 case 2: 5326 /* Hex 2D */ 5327 if ((p >= vStart) && (p < vEnd)) { 5328 /* Old vertices stay the same */ 5329 ++numLeavesNew; 5330 } else if ((p >= fStart) && (p < fEnd)) { 5331 /* Old faces add new faces and vertex */ 5332 numLeavesNew += 1 + 2; 5333 } else if ((p >= cStart) && (p < cEnd)) { 5334 /* Old cells add new cells and interior faces */ 5335 numLeavesNew += 4 + 4; 5336 } 5337 break; 5338 default: 5339 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5340 } 5341 } 5342 /* Communicate depthSizes for each remote rank */ 5343 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 5344 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 5345 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 5346 ierr = PetscMalloc7(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthMaxOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr); 5347 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 5348 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 5349 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 5350 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 5351 for (n = 0; n < numNeighbors; ++n) { 5352 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 5353 } 5354 depthSizeOld[depth] = cMax; 5355 depthSizeOld[0] = vMax; 5356 depthSizeOld[depth-1] = fMax; 5357 depthSizeOld[1] = eMax; 5358 5359 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 5360 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 5361 5362 depthSizeOld[depth] = cEnd - cStart; 5363 depthSizeOld[0] = vEnd - vStart; 5364 depthSizeOld[depth-1] = fEnd - fStart; 5365 depthSizeOld[1] = eEnd - eStart; 5366 5367 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 5368 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 5369 for (n = 0; n < numNeighbors; ++n) { 5370 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 5371 } 5372 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 5373 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 5374 /* Calculate new point SF */ 5375 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 5376 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 5377 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 5378 for (l = 0, m = 0; l < numLeaves; ++l) { 5379 PetscInt p = localPoints[l]; 5380 PetscInt rp = remotePoints[l].index, n; 5381 PetscMPIInt rrank = remotePoints[l].rank; 5382 5383 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 5384 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 5385 switch (refiner) { 5386 case 1: 5387 /* Simplicial 2D */ 5388 if ((p >= vStart) && (p < vEnd)) { 5389 /* Old vertices stay the same */ 5390 localPointsNew[m] = vStartNew + (p - vStart); 5391 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5392 remotePointsNew[m].rank = rrank; 5393 ++m; 5394 } else if ((p >= fStart) && (p < fEnd)) { 5395 /* Old faces add new faces and vertex */ 5396 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5397 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5398 remotePointsNew[m].rank = rrank; 5399 ++m; 5400 for (r = 0; r < 2; ++r, ++m) { 5401 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5402 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5403 remotePointsNew[m].rank = rrank; 5404 } 5405 } else if ((p >= cStart) && (p < cEnd)) { 5406 /* Old cells add new cells and interior faces */ 5407 for (r = 0; r < 4; ++r, ++m) { 5408 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5409 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5410 remotePointsNew[m].rank = rrank; 5411 } 5412 for (r = 0; r < 3; ++r, ++m) { 5413 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5414 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 5415 remotePointsNew[m].rank = rrank; 5416 } 5417 } 5418 break; 5419 case 2: 5420 /* Hex 2D */ 5421 if ((p >= vStart) && (p < vEnd)) { 5422 /* Old vertices stay the same */ 5423 localPointsNew[m] = vStartNew + (p - vStart); 5424 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5425 remotePointsNew[m].rank = rrank; 5426 ++m; 5427 } else if ((p >= fStart) && (p < fEnd)) { 5428 /* Old faces add new faces and vertex */ 5429 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5430 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5431 remotePointsNew[m].rank = rrank; 5432 ++m; 5433 for (r = 0; r < 2; ++r, ++m) { 5434 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5435 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5436 remotePointsNew[m].rank = rrank; 5437 } 5438 } else if ((p >= cStart) && (p < cEnd)) { 5439 /* Old cells add new cells and interior faces */ 5440 for (r = 0; r < 4; ++r, ++m) { 5441 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5442 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5443 remotePointsNew[m].rank = rrank; 5444 } 5445 for (r = 0; r < 4; ++r, ++m) { 5446 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 5447 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 5448 remotePointsNew[m].rank = rrank; 5449 } 5450 } 5451 break; 5452 case 3: 5453 /* Hybrid simplicial 2D */ 5454 if ((p >= vStart) && (p < vEnd)) { 5455 /* Old vertices stay the same */ 5456 localPointsNew[m] = vStartNew + (p - vStart); 5457 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5458 remotePointsNew[m].rank = rrank; 5459 ++m; 5460 } else if ((p >= fStart) && (p < fMax)) { 5461 /* Old interior faces add new faces and vertex */ 5462 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5463 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5464 remotePointsNew[m].rank = rrank; 5465 ++m; 5466 for (r = 0; r < 2; ++r, ++m) { 5467 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5468 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5469 remotePointsNew[m].rank = rrank; 5470 } 5471 } else if ((p >= fMax) && (p < fEnd)) { 5472 /* Old hybrid faces stay the same */ 5473 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 5474 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 5475 remotePointsNew[m].rank = rrank; 5476 ++m; 5477 } else if ((p >= cStart) && (p < cMax)) { 5478 /* Old interior cells add new cells and interior faces */ 5479 for (r = 0; r < 4; ++r, ++m) { 5480 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5481 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5482 remotePointsNew[m].rank = rrank; 5483 } 5484 for (r = 0; r < 3; ++r, ++m) { 5485 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 5486 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 5487 remotePointsNew[m].rank = rrank; 5488 } 5489 } else if ((p >= cStart) && (p < cMax)) { 5490 /* Old hybrid cells add new cells and hybrid face */ 5491 for (r = 0; r < 2; ++r, ++m) { 5492 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5493 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5494 remotePointsNew[m].rank = rrank; 5495 } 5496 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 5497 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth]); 5498 remotePointsNew[m].rank = rrank; 5499 ++m; 5500 } 5501 break; 5502 default: 5503 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5504 } 5505 } 5506 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 5507 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 5508 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 5509 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 5510 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 5511 PetscFunctionReturn(0); 5512 } 5513 5514 #undef __FUNCT__ 5515 #define __FUNCT__ "CellRefinerCreateLabels" 5516 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5517 { 5518 PetscInt numLabels, l; 5519 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 5520 PetscErrorCode ierr; 5521 5522 PetscFunctionBegin; 5523 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5524 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5525 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5526 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5527 5528 cStartNew = 0; 5529 vStartNew = depthSize[2]; 5530 fStartNew = depthSize[2] + depthSize[0]; 5531 5532 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 5533 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5534 switch (refiner) { 5535 case 3: 5536 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5537 cMax = PetscMin(cEnd, cMax); 5538 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5539 fMax = PetscMin(fEnd, fMax); 5540 } 5541 for (l = 0; l < numLabels; ++l) { 5542 DMLabel label, labelNew; 5543 const char *lname; 5544 PetscBool isDepth; 5545 IS valueIS; 5546 const PetscInt *values; 5547 PetscInt numValues, val; 5548 5549 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 5550 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 5551 if (isDepth) continue; 5552 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 5553 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 5554 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 5555 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 5556 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 5557 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 5558 for (val = 0; val < numValues; ++val) { 5559 IS pointIS; 5560 const PetscInt *points; 5561 PetscInt numPoints, n; 5562 5563 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 5564 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 5565 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 5566 for (n = 0; n < numPoints; ++n) { 5567 const PetscInt p = points[n]; 5568 switch (refiner) { 5569 case 1: 5570 /* Simplicial 2D */ 5571 if ((p >= vStart) && (p < vEnd)) { 5572 /* Old vertices stay the same */ 5573 newp = vStartNew + (p - vStart); 5574 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5575 } else if ((p >= fStart) && (p < fEnd)) { 5576 /* Old faces add new faces and vertex */ 5577 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5578 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5579 for (r = 0; r < 2; ++r) { 5580 newp = fStartNew + (p - fStart)*2 + r; 5581 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5582 } 5583 } else if ((p >= cStart) && (p < cEnd)) { 5584 /* Old cells add new cells and interior faces */ 5585 for (r = 0; r < 4; ++r) { 5586 newp = cStartNew + (p - cStart)*4 + r; 5587 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5588 } 5589 for (r = 0; r < 3; ++r) { 5590 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5591 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5592 } 5593 } 5594 break; 5595 case 2: 5596 /* Hex 2D */ 5597 if ((p >= vStart) && (p < vEnd)) { 5598 /* Old vertices stay the same */ 5599 newp = vStartNew + (p - vStart); 5600 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5601 } else if ((p >= fStart) && (p < fEnd)) { 5602 /* Old faces add new faces and vertex */ 5603 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5604 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5605 for (r = 0; r < 2; ++r) { 5606 newp = fStartNew + (p - fStart)*2 + r; 5607 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5608 } 5609 } else if ((p >= cStart) && (p < cEnd)) { 5610 /* Old cells add new cells and interior faces and vertex */ 5611 for (r = 0; r < 4; ++r) { 5612 newp = cStartNew + (p - cStart)*4 + r; 5613 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5614 } 5615 for (r = 0; r < 4; ++r) { 5616 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 5617 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5618 } 5619 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 5620 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5621 } 5622 break; 5623 case 3: 5624 /* Hybrid simplicial 2D */ 5625 if ((p >= vStart) && (p < vEnd)) { 5626 /* Old vertices stay the same */ 5627 newp = vStartNew + (p - vStart); 5628 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5629 } else if ((p >= fStart) && (p < fMax)) { 5630 /* Old interior faces add new faces and vertex */ 5631 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5632 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5633 for (r = 0; r < 2; ++r) { 5634 newp = fStartNew + (p - fStart)*2 + r; 5635 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5636 } 5637 } else if ((p >= fMax) && (p < fEnd)) { 5638 /* Old hybrid faces stay the same */ 5639 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 5640 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5641 } else if ((p >= cStart) && (p < cMax)) { 5642 /* Old interior cells add new cells and interior faces */ 5643 for (r = 0; r < 4; ++r) { 5644 newp = cStartNew + (p - cStart)*4 + r; 5645 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5646 } 5647 for (r = 0; r < 3; ++r) { 5648 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5649 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5650 } 5651 } else if ((p >= cMax) && (p < cEnd)) { 5652 /* Old hybrid cells add new cells and hybrid face */ 5653 for (r = 0; r < 2; ++r) { 5654 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 5655 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5656 } 5657 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 5658 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5659 } 5660 break; 5661 default: 5662 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5663 } 5664 } 5665 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 5666 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 5667 } 5668 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 5669 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 5670 if (0) { 5671 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 5672 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 5673 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 5674 } 5675 } 5676 PetscFunctionReturn(0); 5677 } 5678 5679 #undef __FUNCT__ 5680 #define __FUNCT__ "DMPlexRefine_Uniform" 5681 /* This will only work for interpolated meshes */ 5682 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 5683 { 5684 DM rdm; 5685 PetscInt *depthSize; 5686 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 5687 PetscErrorCode ierr; 5688 5689 PetscFunctionBegin; 5690 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 5691 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 5692 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5693 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 5694 /* Calculate number of new points of each depth */ 5695 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5696 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 5697 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 5698 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 5699 /* Step 1: Set chart */ 5700 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 5701 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 5702 /* Step 2: Set cone/support sizes */ 5703 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5704 /* Step 3: Setup refined DM */ 5705 ierr = DMSetUp(rdm);CHKERRQ(ierr); 5706 /* Step 4: Set cones and supports */ 5707 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5708 /* Step 5: Stratify */ 5709 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 5710 /* Step 6: Set coordinates for vertices */ 5711 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5712 /* Step 7: Create pointSF */ 5713 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5714 /* Step 8: Create labels */ 5715 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5716 ierr = PetscFree(depthSize);CHKERRQ(ierr); 5717 5718 *dmRefined = rdm; 5719 PetscFunctionReturn(0); 5720 } 5721 5722 #undef __FUNCT__ 5723 #define __FUNCT__ "DMPlexSetRefinementUniform" 5724 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 5725 { 5726 DM_Plex *mesh = (DM_Plex*) dm->data; 5727 5728 PetscFunctionBegin; 5729 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5730 mesh->refinementUniform = refinementUniform; 5731 PetscFunctionReturn(0); 5732 } 5733 5734 #undef __FUNCT__ 5735 #define __FUNCT__ "DMPlexGetRefinementUniform" 5736 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 5737 { 5738 DM_Plex *mesh = (DM_Plex*) dm->data; 5739 5740 PetscFunctionBegin; 5741 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5742 PetscValidPointer(refinementUniform, 2); 5743 *refinementUniform = mesh->refinementUniform; 5744 PetscFunctionReturn(0); 5745 } 5746 5747 #undef __FUNCT__ 5748 #define __FUNCT__ "DMPlexSetRefinementLimit" 5749 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 5750 { 5751 DM_Plex *mesh = (DM_Plex*) dm->data; 5752 5753 PetscFunctionBegin; 5754 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5755 mesh->refinementLimit = refinementLimit; 5756 PetscFunctionReturn(0); 5757 } 5758 5759 #undef __FUNCT__ 5760 #define __FUNCT__ "DMPlexGetRefinementLimit" 5761 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 5762 { 5763 DM_Plex *mesh = (DM_Plex*) dm->data; 5764 5765 PetscFunctionBegin; 5766 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5767 PetscValidPointer(refinementLimit, 2); 5768 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 5769 *refinementLimit = mesh->refinementLimit; 5770 PetscFunctionReturn(0); 5771 } 5772 5773 #undef __FUNCT__ 5774 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 5775 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 5776 { 5777 PetscInt dim, cStart, coneSize, cMax; 5778 PetscErrorCode ierr; 5779 5780 PetscFunctionBegin; 5781 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5782 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 5783 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 5784 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5785 switch (dim) { 5786 case 2: 5787 switch (coneSize) { 5788 case 3: 5789 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 5790 else *cellRefiner = 1; /* Triangular */ 5791 break; 5792 case 4: 5793 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 5794 else *cellRefiner = 2; /* Quadrilateral */ 5795 break; 5796 default: 5797 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 5798 } 5799 break; 5800 default: 5801 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 5802 } 5803 PetscFunctionReturn(0); 5804 } 5805 5806 #undef __FUNCT__ 5807 #define __FUNCT__ "DMRefine_Plex" 5808 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 5809 { 5810 PetscReal refinementLimit; 5811 PetscInt dim, cStart, cEnd; 5812 char genname[1024], *name = NULL; 5813 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5814 PetscErrorCode ierr; 5815 5816 PetscFunctionBegin; 5817 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 5818 if (isUniform) { 5819 CellRefiner cellRefiner; 5820 5821 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 5822 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 5823 PetscFunctionReturn(0); 5824 } 5825 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 5826 if (refinementLimit == 0.0) PetscFunctionReturn(0); 5827 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5828 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5829 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5830 if (flg) name = genname; 5831 if (name) { 5832 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5833 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5834 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5835 } 5836 switch (dim) { 5837 case 2: 5838 if (!name || isTriangle) { 5839 #if defined(PETSC_HAVE_TRIANGLE) 5840 double *maxVolumes; 5841 PetscInt c; 5842 5843 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 5844 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5845 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5846 ierr = PetscFree(maxVolumes);CHKERRQ(ierr); 5847 #else 5848 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 5849 #endif 5850 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5851 break; 5852 case 3: 5853 if (!name || isCTetgen) { 5854 #if defined(PETSC_HAVE_CTETGEN) 5855 PetscReal *maxVolumes; 5856 PetscInt c; 5857 5858 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 5859 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5860 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5861 #else 5862 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5863 #endif 5864 } else if (isTetgen) { 5865 #if defined(PETSC_HAVE_TETGEN) 5866 double *maxVolumes; 5867 PetscInt c; 5868 5869 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 5870 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5871 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5872 #else 5873 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5874 #endif 5875 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5876 break; 5877 default: 5878 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 5879 } 5880 PetscFunctionReturn(0); 5881 } 5882 5883 #undef __FUNCT__ 5884 #define __FUNCT__ "DMPlexGetDepth" 5885 /*@ 5886 DMPlexGetDepth - get the number of strata 5887 5888 Not Collective 5889 5890 Input Parameters: 5891 . dm - The DMPlex object 5892 5893 Output Parameters: 5894 . depth - number of strata 5895 5896 Level: developer 5897 5898 Notes: 5899 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 5900 5901 .keywords: mesh, points 5902 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 5903 @*/ 5904 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5905 { 5906 PetscInt d; 5907 PetscErrorCode ierr; 5908 5909 PetscFunctionBegin; 5910 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5911 PetscValidPointer(depth, 2); 5912 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 5913 *depth = d-1; 5914 PetscFunctionReturn(0); 5915 } 5916 5917 #undef __FUNCT__ 5918 #define __FUNCT__ "DMPlexGetDepthStratum" 5919 /*@ 5920 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 5921 5922 Not Collective 5923 5924 Input Parameters: 5925 + dm - The DMPlex object 5926 - stratumValue - The requested depth 5927 5928 Output Parameters: 5929 + start - The first point at this depth 5930 - end - One beyond the last point at this depth 5931 5932 Level: developer 5933 5934 .keywords: mesh, points 5935 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 5936 @*/ 5937 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 5938 { 5939 DM_Plex *mesh = (DM_Plex*) dm->data; 5940 DMLabel next = mesh->labels; 5941 PetscBool flg = PETSC_FALSE; 5942 PetscInt depth; 5943 PetscErrorCode ierr; 5944 5945 PetscFunctionBegin; 5946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5947 if (stratumValue < 0) { 5948 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 5949 PetscFunctionReturn(0); 5950 } else { 5951 PetscInt pStart, pEnd; 5952 5953 if (start) *start = 0; 5954 if (end) *end = 0; 5955 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5956 if (pStart == pEnd) PetscFunctionReturn(0); 5957 } 5958 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 5959 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 5960 /* We should have a generic GetLabel() and a Label class */ 5961 while (next) { 5962 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 5963 if (flg) break; 5964 next = next->next; 5965 } 5966 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 5967 depth = stratumValue; 5968 if ((depth < 0) || (depth >= next->numStrata)) { 5969 if (start) *start = 0; 5970 if (end) *end = 0; 5971 } else { 5972 if (start) *start = next->points[next->stratumOffsets[depth]]; 5973 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 5974 } 5975 PetscFunctionReturn(0); 5976 } 5977 5978 #undef __FUNCT__ 5979 #define __FUNCT__ "DMPlexGetHeightStratum" 5980 /*@ 5981 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 5982 5983 Not Collective 5984 5985 Input Parameters: 5986 + dm - The DMPlex object 5987 - stratumValue - The requested height 5988 5989 Output Parameters: 5990 + start - The first point at this height 5991 - end - One beyond the last point at this height 5992 5993 Level: developer 5994 5995 .keywords: mesh, points 5996 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 5997 @*/ 5998 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 5999 { 6000 DM_Plex *mesh = (DM_Plex*) dm->data; 6001 DMLabel next = mesh->labels; 6002 PetscBool flg = PETSC_FALSE; 6003 PetscInt depth; 6004 PetscErrorCode ierr; 6005 6006 PetscFunctionBegin; 6007 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6008 if (stratumValue < 0) { 6009 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 6010 } else { 6011 PetscInt pStart, pEnd; 6012 6013 if (start) *start = 0; 6014 if (end) *end = 0; 6015 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6016 if (pStart == pEnd) PetscFunctionReturn(0); 6017 } 6018 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6019 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6020 /* We should have a generic GetLabel() and a Label class */ 6021 while (next) { 6022 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6023 if (flg) break; 6024 next = next->next; 6025 } 6026 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6027 depth = next->stratumValues[next->numStrata-1] - stratumValue; 6028 if ((depth < 0) || (depth >= next->numStrata)) { 6029 if (start) *start = 0; 6030 if (end) *end = 0; 6031 } else { 6032 if (start) *start = next->points[next->stratumOffsets[depth]]; 6033 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 6034 } 6035 PetscFunctionReturn(0); 6036 } 6037 6038 #undef __FUNCT__ 6039 #define __FUNCT__ "DMPlexCreateSectionInitial" 6040 /* Set the number of dof on each point and separate by fields */ 6041 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 6042 { 6043 PetscInt *numDofTot; 6044 PetscInt pStart = 0, pEnd = 0; 6045 PetscInt p, d, f; 6046 PetscErrorCode ierr; 6047 6048 PetscFunctionBegin; 6049 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 6050 for (d = 0; d <= dim; ++d) { 6051 numDofTot[d] = 0; 6052 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 6053 } 6054 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 6055 if (numFields > 0) { 6056 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 6057 if (numComp) { 6058 for (f = 0; f < numFields; ++f) { 6059 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 6060 } 6061 } 6062 } 6063 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6064 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 6065 for (d = 0; d <= dim; ++d) { 6066 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 6067 for (p = pStart; p < pEnd; ++p) { 6068 for (f = 0; f < numFields; ++f) { 6069 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 6070 } 6071 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 6072 } 6073 } 6074 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 6075 PetscFunctionReturn(0); 6076 } 6077 6078 #undef __FUNCT__ 6079 #define __FUNCT__ "DMPlexCreateSectionBCDof" 6080 /* Set the number of dof on each point and separate by fields 6081 If constDof is PETSC_DETERMINE, constrain every dof on the point 6082 */ 6083 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 6084 { 6085 PetscInt numFields; 6086 PetscInt bc; 6087 PetscErrorCode ierr; 6088 6089 PetscFunctionBegin; 6090 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6091 for (bc = 0; bc < numBC; ++bc) { 6092 PetscInt field = 0; 6093 const PetscInt *idx; 6094 PetscInt n, i; 6095 6096 if (numFields) field = bcField[bc]; 6097 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 6098 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6099 for (i = 0; i < n; ++i) { 6100 const PetscInt p = idx[i]; 6101 PetscInt numConst = constDof; 6102 6103 /* Constrain every dof on the point */ 6104 if (numConst < 0) { 6105 if (numFields) { 6106 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 6107 } else { 6108 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 6109 } 6110 } 6111 if (numFields) { 6112 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 6113 } 6114 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 6115 } 6116 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6117 } 6118 PetscFunctionReturn(0); 6119 } 6120 6121 #undef __FUNCT__ 6122 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 6123 /* Set the constrained indices on each point and separate by fields */ 6124 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 6125 { 6126 PetscInt *maxConstraints; 6127 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 6128 PetscErrorCode ierr; 6129 6130 PetscFunctionBegin; 6131 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6132 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6133 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 6134 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 6135 for (p = pStart; p < pEnd; ++p) { 6136 PetscInt cdof; 6137 6138 if (numFields) { 6139 for (f = 0; f < numFields; ++f) { 6140 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 6141 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 6142 } 6143 } else { 6144 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6145 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 6146 } 6147 } 6148 for (f = 0; f < numFields; ++f) { 6149 maxConstraints[numFields] += maxConstraints[f]; 6150 } 6151 if (maxConstraints[numFields]) { 6152 PetscInt *indices; 6153 6154 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 6155 for (p = pStart; p < pEnd; ++p) { 6156 PetscInt cdof, d; 6157 6158 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6159 if (cdof) { 6160 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 6161 if (numFields) { 6162 PetscInt numConst = 0, foff = 0; 6163 6164 for (f = 0; f < numFields; ++f) { 6165 PetscInt cfdof, fdof; 6166 6167 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 6168 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 6169 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 6170 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 6171 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 6172 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 6173 numConst += cfdof; 6174 foff += fdof; 6175 } 6176 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 6177 } else { 6178 for (d = 0; d < cdof; ++d) indices[d] = d; 6179 } 6180 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 6181 } 6182 } 6183 ierr = PetscFree(indices);CHKERRQ(ierr); 6184 } 6185 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 6186 PetscFunctionReturn(0); 6187 } 6188 6189 #undef __FUNCT__ 6190 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 6191 /* Set the constrained field indices on each point */ 6192 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 6193 { 6194 const PetscInt *points, *indices; 6195 PetscInt numFields, maxDof, numPoints, p, numConstraints; 6196 PetscErrorCode ierr; 6197 6198 PetscFunctionBegin; 6199 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6200 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 6201 6202 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 6203 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 6204 if (!constraintIndices) { 6205 PetscInt *idx, i; 6206 6207 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6208 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 6209 for (i = 0; i < maxDof; ++i) idx[i] = i; 6210 for (p = 0; p < numPoints; ++p) { 6211 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 6212 } 6213 ierr = PetscFree(idx);CHKERRQ(ierr); 6214 } else { 6215 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 6216 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 6217 for (p = 0; p < numPoints; ++p) { 6218 PetscInt fcdof; 6219 6220 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 6221 if (fcdof != numConstraints) SETERRQ4(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints); 6222 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 6223 } 6224 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 6225 } 6226 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 6227 PetscFunctionReturn(0); 6228 } 6229 6230 #undef __FUNCT__ 6231 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 6232 /* Set the constrained indices on each point and separate by fields */ 6233 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 6234 { 6235 PetscInt *indices; 6236 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 6237 PetscErrorCode ierr; 6238 6239 PetscFunctionBegin; 6240 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6241 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 6242 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6243 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 6244 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6245 for (p = pStart; p < pEnd; ++p) { 6246 PetscInt cdof, d; 6247 6248 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6249 if (cdof) { 6250 PetscInt numConst = 0, foff = 0; 6251 6252 for (f = 0; f < numFields; ++f) { 6253 const PetscInt *fcind; 6254 PetscInt fdof, fcdof; 6255 6256 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 6257 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 6258 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 6259 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 6260 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 6261 foff += fdof; 6262 numConst += fcdof; 6263 } 6264 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 6265 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 6266 } 6267 } 6268 ierr = PetscFree(indices);CHKERRQ(ierr); 6269 PetscFunctionReturn(0); 6270 } 6271 6272 #undef __FUNCT__ 6273 #define __FUNCT__ "DMPlexCreateSection" 6274 /*@C 6275 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 6276 6277 Not Collective 6278 6279 Input Parameters: 6280 + dm - The DMPlex object 6281 . dim - The spatial dimension of the problem 6282 . numFields - The number of fields in the problem 6283 . numComp - An array of size numFields that holds the number of components for each field 6284 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 6285 . numBC - The number of boundary conditions 6286 . bcField - An array of size numBC giving the field number for each boundry condition 6287 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 6288 6289 Output Parameter: 6290 . section - The PetscSection object 6291 6292 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 6293 nubmer of dof for field 0 on each edge. 6294 6295 Level: developer 6296 6297 Fortran Notes: 6298 A Fortran 90 version is available as DMPlexCreateSectionF90() 6299 6300 .keywords: mesh, elements 6301 .seealso: DMPlexCreate(), PetscSectionCreate() 6302 @*/ 6303 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 6304 { 6305 PetscErrorCode ierr; 6306 6307 PetscFunctionBegin; 6308 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 6309 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 6310 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 6311 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 6312 { 6313 PetscBool view = PETSC_FALSE; 6314 6315 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 6316 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 6317 } 6318 PetscFunctionReturn(0); 6319 } 6320 6321 #undef __FUNCT__ 6322 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 6323 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 6324 { 6325 PetscSection section; 6326 PetscErrorCode ierr; 6327 6328 PetscFunctionBegin; 6329 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 6330 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6331 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 6332 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6333 PetscFunctionReturn(0); 6334 } 6335 6336 #undef __FUNCT__ 6337 #define __FUNCT__ "DMPlexGetCoordinateSection" 6338 /*@ 6339 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6340 6341 Not Collective 6342 6343 Input Parameter: 6344 . dm - The DMPlex object 6345 6346 Output Parameter: 6347 . section - The PetscSection object 6348 6349 Level: intermediate 6350 6351 .keywords: mesh, coordinates 6352 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6353 @*/ 6354 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 6355 { 6356 DM cdm; 6357 PetscErrorCode ierr; 6358 6359 PetscFunctionBegin; 6360 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6361 PetscValidPointer(section, 2); 6362 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6363 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 6364 PetscFunctionReturn(0); 6365 } 6366 6367 #undef __FUNCT__ 6368 #define __FUNCT__ "DMPlexSetCoordinateSection" 6369 /*@ 6370 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 6371 6372 Not Collective 6373 6374 Input Parameters: 6375 + dm - The DMPlex object 6376 - section - The PetscSection object 6377 6378 Level: intermediate 6379 6380 .keywords: mesh, coordinates 6381 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6382 @*/ 6383 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 6384 { 6385 DM cdm; 6386 PetscErrorCode ierr; 6387 6388 PetscFunctionBegin; 6389 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6390 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 6391 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6392 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 6393 PetscFunctionReturn(0); 6394 } 6395 6396 #undef __FUNCT__ 6397 #define __FUNCT__ "DMPlexGetConeSection" 6398 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 6399 { 6400 DM_Plex *mesh = (DM_Plex*) dm->data; 6401 6402 PetscFunctionBegin; 6403 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6404 if (section) *section = mesh->coneSection; 6405 PetscFunctionReturn(0); 6406 } 6407 6408 #undef __FUNCT__ 6409 #define __FUNCT__ "DMPlexGetCones" 6410 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 6411 { 6412 DM_Plex *mesh = (DM_Plex*) dm->data; 6413 6414 PetscFunctionBegin; 6415 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6416 if (cones) *cones = mesh->cones; 6417 PetscFunctionReturn(0); 6418 } 6419 6420 #undef __FUNCT__ 6421 #define __FUNCT__ "DMPlexGetConeOrientations" 6422 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 6423 { 6424 DM_Plex *mesh = (DM_Plex*) dm->data; 6425 6426 PetscFunctionBegin; 6427 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6428 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 6429 PetscFunctionReturn(0); 6430 } 6431 6432 /******************************** FEM Support **********************************/ 6433 6434 #undef __FUNCT__ 6435 #define __FUNCT__ "DMPlexVecGetClosure" 6436 /*@C 6437 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6438 6439 Not collective 6440 6441 Input Parameters: 6442 + dm - The DM 6443 . section - The section describing the layout in v, or NULL to use the default section 6444 . v - The local vector 6445 - point - The sieve point in the DM 6446 6447 Output Parameters: 6448 + csize - The number of values in the closure, or NULL 6449 - values - The array of values, which is a borrowed array and should not be freed 6450 6451 Fortran Notes: 6452 Since it returns an array, this routine is only available in Fortran 90, and you must 6453 include petsc.h90 in your code. 6454 6455 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6456 6457 Level: intermediate 6458 6459 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6460 @*/ 6461 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6462 { 6463 PetscScalar *array, *vArray; 6464 PetscInt *points = NULL; 6465 PetscInt offsets[32]; 6466 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 6467 PetscErrorCode ierr; 6468 6469 PetscFunctionBegin; 6470 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6471 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6472 if (!section) { 6473 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6474 } 6475 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6476 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6477 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6478 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6479 /* Compress out points not in the section */ 6480 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6481 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6482 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6483 points[q*2] = points[p]; 6484 points[q*2+1] = points[p+1]; 6485 ++q; 6486 } 6487 } 6488 numPoints = q; 6489 for (p = 0, size = 0; p < numPoints*2; p += 2) { 6490 PetscInt dof, fdof; 6491 6492 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6493 for (f = 0; f < numFields; ++f) { 6494 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6495 offsets[f+1] += fdof; 6496 } 6497 size += dof; 6498 } 6499 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6500 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 6501 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 6502 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 6503 for (p = 0; p < numPoints*2; p += 2) { 6504 PetscInt o = points[p+1]; 6505 PetscInt dof, off, d; 6506 PetscScalar *varr; 6507 6508 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6509 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 6510 varr = &vArray[off]; 6511 if (numFields) { 6512 PetscInt fdof, foff, fcomp, f, c; 6513 6514 for (f = 0, foff = 0; f < numFields; ++f) { 6515 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6516 if (o >= 0) { 6517 for (d = 0; d < fdof; ++d, ++offsets[f]) { 6518 array[offsets[f]] = varr[foff+d]; 6519 } 6520 } else { 6521 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6522 for (d = fdof/fcomp-1; d >= 0; --d) { 6523 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 6524 array[offsets[f]] = varr[foff+d*fcomp+c]; 6525 } 6526 } 6527 } 6528 foff += fdof; 6529 } 6530 } else { 6531 if (o >= 0) { 6532 for (d = 0; d < dof; ++d, ++offsets[0]) { 6533 array[offsets[0]] = varr[d]; 6534 } 6535 } else { 6536 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 6537 array[offsets[0]] = varr[d]; 6538 } 6539 } 6540 } 6541 } 6542 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6543 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 6544 if (csize) *csize = size; 6545 *values = array; 6546 PetscFunctionReturn(0); 6547 } 6548 6549 #undef __FUNCT__ 6550 #define __FUNCT__ "DMPlexVecRestoreClosure" 6551 /*@C 6552 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6553 6554 Not collective 6555 6556 Input Parameters: 6557 + dm - The DM 6558 . section - The section describing the layout in v, or NULL to use the default section 6559 . v - The local vector 6560 . point - The sieve point in the DM 6561 . csize - The number of values in the closure, or NULL 6562 - values - The array of values, which is a borrowed array and should not be freed 6563 6564 Fortran Notes: 6565 Since it returns an array, this routine is only available in Fortran 90, and you must 6566 include petsc.h90 in your code. 6567 6568 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6569 6570 Level: intermediate 6571 6572 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6573 @*/ 6574 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6575 { 6576 PetscInt size = 0; 6577 PetscErrorCode ierr; 6578 6579 PetscFunctionBegin; 6580 /* Should work without recalculating size */ 6581 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 6582 PetscFunctionReturn(0); 6583 } 6584 6585 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 6586 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 6587 6588 #undef __FUNCT__ 6589 #define __FUNCT__ "updatePoint_private" 6590 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6591 { 6592 PetscInt cdof; /* The number of constraints on this point */ 6593 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6594 PetscScalar *a; 6595 PetscInt off, cind = 0, k; 6596 PetscErrorCode ierr; 6597 6598 PetscFunctionBegin; 6599 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6600 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6601 a = &array[off]; 6602 if (!cdof || setBC) { 6603 if (orientation >= 0) { 6604 for (k = 0; k < dof; ++k) { 6605 fuse(&a[k], values[k]); 6606 } 6607 } else { 6608 for (k = 0; k < dof; ++k) { 6609 fuse(&a[k], values[dof-k-1]); 6610 } 6611 } 6612 } else { 6613 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6614 if (orientation >= 0) { 6615 for (k = 0; k < dof; ++k) { 6616 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6617 fuse(&a[k], values[k]); 6618 } 6619 } else { 6620 for (k = 0; k < dof; ++k) { 6621 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6622 fuse(&a[k], values[dof-k-1]); 6623 } 6624 } 6625 } 6626 PetscFunctionReturn(0); 6627 } 6628 6629 #undef __FUNCT__ 6630 #define __FUNCT__ "updatePointFields_private" 6631 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6632 { 6633 PetscScalar *a; 6634 PetscInt numFields, off, foff, f; 6635 PetscErrorCode ierr; 6636 6637 PetscFunctionBegin; 6638 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6639 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6640 a = &array[off]; 6641 for (f = 0, foff = 0; f < numFields; ++f) { 6642 PetscInt fdof, fcomp, fcdof; 6643 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6644 PetscInt cind = 0, k, c; 6645 6646 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6647 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6648 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6649 if (!fcdof || setBC) { 6650 if (orientation >= 0) { 6651 for (k = 0; k < fdof; ++k) { 6652 fuse(&a[foff+k], values[foffs[f]+k]); 6653 } 6654 } else { 6655 for (k = fdof/fcomp-1; k >= 0; --k) { 6656 for (c = 0; c < fcomp; ++c) { 6657 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6658 } 6659 } 6660 } 6661 } else { 6662 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6663 if (orientation >= 0) { 6664 for (k = 0; k < fdof; ++k) { 6665 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 6666 fuse(&a[foff+k], values[foffs[f]+k]); 6667 } 6668 } else { 6669 for (k = fdof/fcomp-1; k >= 0; --k) { 6670 for (c = 0; c < fcomp; ++c) { 6671 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 6672 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6673 } 6674 } 6675 } 6676 } 6677 foff += fdof; 6678 foffs[f] += fdof; 6679 } 6680 PetscFunctionReturn(0); 6681 } 6682 6683 #undef __FUNCT__ 6684 #define __FUNCT__ "DMPlexVecSetClosure" 6685 /*@C 6686 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6687 6688 Not collective 6689 6690 Input Parameters: 6691 + dm - The DM 6692 . section - The section describing the layout in v, or NULL to use the default section 6693 . v - The local vector 6694 . point - The sieve point in the DM 6695 . values - The array of values 6696 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6697 6698 Fortran Notes: 6699 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6700 6701 Level: intermediate 6702 6703 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6704 @*/ 6705 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6706 { 6707 PetscScalar *array; 6708 PetscInt *points = NULL; 6709 PetscInt offsets[32]; 6710 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 6711 PetscErrorCode ierr; 6712 6713 PetscFunctionBegin; 6714 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6715 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6716 if (!section) { 6717 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6718 } 6719 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6720 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6721 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6722 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6723 /* Compress out points not in the section */ 6724 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6725 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6726 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6727 points[q*2] = points[p]; 6728 points[q*2+1] = points[p+1]; 6729 ++q; 6730 } 6731 } 6732 numPoints = q; 6733 for (p = 0; p < numPoints*2; p += 2) { 6734 PetscInt fdof; 6735 6736 for (f = 0; f < numFields; ++f) { 6737 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6738 offsets[f+1] += fdof; 6739 } 6740 } 6741 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6742 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6743 if (numFields) { 6744 switch (mode) { 6745 case INSERT_VALUES: 6746 for (p = 0; p < numPoints*2; p += 2) { 6747 PetscInt o = points[p+1]; 6748 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 6749 } break; 6750 case INSERT_ALL_VALUES: 6751 for (p = 0; p < numPoints*2; p += 2) { 6752 PetscInt o = points[p+1]; 6753 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 6754 } break; 6755 case ADD_VALUES: 6756 for (p = 0; p < numPoints*2; p += 2) { 6757 PetscInt o = points[p+1]; 6758 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 6759 } break; 6760 case ADD_ALL_VALUES: 6761 for (p = 0; p < numPoints*2; p += 2) { 6762 PetscInt o = points[p+1]; 6763 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 6764 } break; 6765 default: 6766 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 6767 } 6768 } else { 6769 switch (mode) { 6770 case INSERT_VALUES: 6771 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6772 PetscInt o = points[p+1]; 6773 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6774 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 6775 } break; 6776 case INSERT_ALL_VALUES: 6777 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6778 PetscInt o = points[p+1]; 6779 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6780 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 6781 } break; 6782 case ADD_VALUES: 6783 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6784 PetscInt o = points[p+1]; 6785 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6786 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 6787 } break; 6788 case ADD_ALL_VALUES: 6789 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6790 PetscInt o = points[p+1]; 6791 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6792 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 6793 } break; 6794 default: 6795 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 6796 } 6797 } 6798 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6799 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6800 PetscFunctionReturn(0); 6801 } 6802 6803 #undef __FUNCT__ 6804 #define __FUNCT__ "DMPlexPrintMatSetValues" 6805 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], const PetscScalar values[]) 6806 { 6807 PetscMPIInt rank; 6808 PetscInt i, j; 6809 PetscErrorCode ierr; 6810 6811 PetscFunctionBegin; 6812 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 6813 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 6814 for (i = 0; i < numIndices; i++) { 6815 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 6816 } 6817 for (i = 0; i < numIndices; i++) { 6818 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 6819 for (j = 0; j < numIndices; j++) { 6820 #if defined(PETSC_USE_COMPLEX) 6821 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 6822 #else 6823 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 6824 #endif 6825 } 6826 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6827 } 6828 PetscFunctionReturn(0); 6829 } 6830 6831 #undef __FUNCT__ 6832 #define __FUNCT__ "indicesPoint_private" 6833 /* . off - The global offset of this point */ 6834 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 6835 { 6836 PetscInt dof; /* The number of unknowns on this point */ 6837 PetscInt cdof; /* The number of constraints on this point */ 6838 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6839 PetscInt cind = 0, k; 6840 PetscErrorCode ierr; 6841 6842 PetscFunctionBegin; 6843 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6844 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6845 if (!cdof || setBC) { 6846 if (orientation >= 0) { 6847 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 6848 } else { 6849 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 6850 } 6851 } else { 6852 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6853 if (orientation >= 0) { 6854 for (k = 0; k < dof; ++k) { 6855 if ((cind < cdof) && (k == cdofs[cind])) { 6856 /* Insert check for returning constrained indices */ 6857 indices[*loff+k] = -(off+k+1); 6858 ++cind; 6859 } else { 6860 indices[*loff+k] = off+k-cind; 6861 } 6862 } 6863 } else { 6864 for (k = 0; k < dof; ++k) { 6865 if ((cind < cdof) && (k == cdofs[cind])) { 6866 /* Insert check for returning constrained indices */ 6867 indices[*loff+dof-k-1] = -(off+k+1); 6868 ++cind; 6869 } else { 6870 indices[*loff+dof-k-1] = off+k-cind; 6871 } 6872 } 6873 } 6874 } 6875 *loff += dof; 6876 PetscFunctionReturn(0); 6877 } 6878 6879 #undef __FUNCT__ 6880 #define __FUNCT__ "indicesPointFields_private" 6881 /* . off - The global offset of this point */ 6882 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 6883 { 6884 PetscInt numFields, foff, f; 6885 PetscErrorCode ierr; 6886 6887 PetscFunctionBegin; 6888 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6889 for (f = 0, foff = 0; f < numFields; ++f) { 6890 PetscInt fdof, fcomp, cfdof; 6891 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6892 PetscInt cind = 0, k, c; 6893 6894 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6895 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6896 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6897 if (!cfdof || setBC) { 6898 if (orientation >= 0) { 6899 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 6900 } else { 6901 for (k = fdof/fcomp-1; k >= 0; --k) { 6902 for (c = 0; c < fcomp; ++c) { 6903 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 6904 } 6905 } 6906 } 6907 } else { 6908 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6909 if (orientation >= 0) { 6910 for (k = 0; k < fdof; ++k) { 6911 if ((cind < cfdof) && (k == fcdofs[cind])) { 6912 indices[foffs[f]+k] = -(off+foff+k+1); 6913 ++cind; 6914 } else { 6915 indices[foffs[f]+k] = off+foff+k-cind; 6916 } 6917 } 6918 } else { 6919 for (k = fdof/fcomp-1; k >= 0; --k) { 6920 for (c = 0; c < fcomp; ++c) { 6921 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 6922 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 6923 ++cind; 6924 } else { 6925 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 6926 } 6927 } 6928 } 6929 } 6930 } 6931 foff += fdof - cfdof; 6932 foffs[f] += fdof; 6933 } 6934 PetscFunctionReturn(0); 6935 } 6936 6937 #undef __FUNCT__ 6938 #define __FUNCT__ "DMPlexMatSetClosure" 6939 /*@C 6940 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 6941 6942 Not collective 6943 6944 Input Parameters: 6945 + dm - The DM 6946 . section - The section describing the layout in v, or NULL to use the default section 6947 . globalSection - The section describing the layout in v, or NULL to use the default section 6948 . A - The matrix 6949 . point - The sieve point in the DM 6950 . values - The array of values 6951 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6952 6953 Fortran Notes: 6954 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6955 6956 Level: intermediate 6957 6958 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 6959 @*/ 6960 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6961 { 6962 DM_Plex *mesh = (DM_Plex*) dm->data; 6963 PetscInt *points = NULL; 6964 PetscInt *indices; 6965 PetscInt offsets[32]; 6966 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 6967 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 6968 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 6969 PetscErrorCode ierr; 6970 6971 PetscFunctionBegin; 6972 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6973 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 6974 if (useDefault) { 6975 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6976 } 6977 if (useGlobalDefault) { 6978 if (useDefault) { 6979 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 6980 } else { 6981 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6982 } 6983 } 6984 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6985 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6986 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6987 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6988 /* Compress out points not in the section */ 6989 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6990 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6991 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6992 points[q*2] = points[p]; 6993 points[q*2+1] = points[p+1]; 6994 ++q; 6995 } 6996 } 6997 numPoints = q; 6998 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 6999 PetscInt fdof; 7000 7001 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7002 for (f = 0; f < numFields; ++f) { 7003 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7004 offsets[f+1] += fdof; 7005 } 7006 numIndices += dof; 7007 } 7008 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 7009 7010 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 7011 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 7012 if (numFields) { 7013 for (p = 0; p < numPoints*2; p += 2) { 7014 PetscInt o = points[p+1]; 7015 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 7016 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 7017 } 7018 } else { 7019 for (p = 0, off = 0; p < numPoints*2; p += 2) { 7020 PetscInt o = points[p+1]; 7021 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 7022 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 7023 } 7024 } 7025 if (useGlobalDefault && !useDefault) { 7026 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7027 } 7028 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 7029 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7030 if (ierr) { 7031 PetscMPIInt rank; 7032 PetscErrorCode ierr2; 7033 7034 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 7035 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7036 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 7037 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 7038 CHKERRQ(ierr); 7039 } 7040 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7041 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 7042 PetscFunctionReturn(0); 7043 } 7044 7045 #undef __FUNCT__ 7046 #define __FUNCT__ "DMPlexGetHybridBounds" 7047 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 7048 { 7049 DM_Plex *mesh = (DM_Plex*) dm->data; 7050 PetscInt dim; 7051 PetscErrorCode ierr; 7052 7053 PetscFunctionBegin; 7054 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7055 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7056 if (cMax) *cMax = mesh->hybridPointMax[dim]; 7057 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 7058 if (eMax) *eMax = mesh->hybridPointMax[1]; 7059 if (vMax) *vMax = mesh->hybridPointMax[0]; 7060 PetscFunctionReturn(0); 7061 } 7062 7063 #undef __FUNCT__ 7064 #define __FUNCT__ "DMPlexSetHybridBounds" 7065 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 7066 { 7067 DM_Plex *mesh = (DM_Plex*) dm->data; 7068 PetscInt dim; 7069 PetscErrorCode ierr; 7070 7071 PetscFunctionBegin; 7072 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7073 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7074 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 7075 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 7076 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 7077 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 7078 PetscFunctionReturn(0); 7079 } 7080 7081 #undef __FUNCT__ 7082 #define __FUNCT__ "DMPlexGetVTKCellHeight" 7083 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7084 { 7085 DM_Plex *mesh = (DM_Plex*) dm->data; 7086 7087 PetscFunctionBegin; 7088 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7089 PetscValidPointer(cellHeight, 2); 7090 *cellHeight = mesh->vtkCellHeight; 7091 PetscFunctionReturn(0); 7092 } 7093 7094 #undef __FUNCT__ 7095 #define __FUNCT__ "DMPlexSetVTKCellHeight" 7096 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7097 { 7098 DM_Plex *mesh = (DM_Plex*) dm->data; 7099 7100 PetscFunctionBegin; 7101 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7102 mesh->vtkCellHeight = cellHeight; 7103 PetscFunctionReturn(0); 7104 } 7105 7106 #undef __FUNCT__ 7107 #define __FUNCT__ "DMPlexCreateNumbering_Private" 7108 /* We can easily have a form that takes an IS instead */ 7109 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 7110 { 7111 PetscSection section, globalSection; 7112 PetscInt *numbers, p; 7113 PetscErrorCode ierr; 7114 7115 PetscFunctionBegin; 7116 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7117 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7118 for (p = pStart; p < pEnd; ++p) { 7119 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7120 } 7121 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7122 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7123 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 7124 for (p = pStart; p < pEnd; ++p) { 7125 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7126 } 7127 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7128 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7129 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7130 PetscFunctionReturn(0); 7131 } 7132 7133 #undef __FUNCT__ 7134 #define __FUNCT__ "DMPlexGetCellNumbering" 7135 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7136 { 7137 DM_Plex *mesh = (DM_Plex*) dm->data; 7138 PetscInt cellHeight, cStart, cEnd, cMax; 7139 PetscErrorCode ierr; 7140 7141 PetscFunctionBegin; 7142 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7143 if (!mesh->globalCellNumbers) { 7144 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7145 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 7146 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7147 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7148 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 7149 } 7150 *globalCellNumbers = mesh->globalCellNumbers; 7151 PetscFunctionReturn(0); 7152 } 7153 7154 #undef __FUNCT__ 7155 #define __FUNCT__ "DMPlexGetVertexNumbering" 7156 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7157 { 7158 DM_Plex *mesh = (DM_Plex*) dm->data; 7159 PetscInt vStart, vEnd, vMax; 7160 PetscErrorCode ierr; 7161 7162 PetscFunctionBegin; 7163 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7164 if (!mesh->globalVertexNumbers) { 7165 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7166 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 7167 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 7168 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 7169 } 7170 *globalVertexNumbers = mesh->globalVertexNumbers; 7171 PetscFunctionReturn(0); 7172 } 7173 7174 7175 #undef __FUNCT__ 7176 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 7177 /*@C 7178 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 7179 the local section and an SF describing the section point overlap. 7180 7181 Input Parameters: 7182 + s - The PetscSection for the local field layout 7183 . sf - The SF describing parallel layout of the section points 7184 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 7185 . label - The label specifying the points 7186 - labelValue - The label stratum specifying the points 7187 7188 Output Parameter: 7189 . gsection - The PetscSection for the global field layout 7190 7191 Note: This gives negative sizes and offsets to points not owned by this process 7192 7193 Level: developer 7194 7195 .seealso: PetscSectionCreate() 7196 @*/ 7197 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 7198 { 7199 PetscInt *neg; 7200 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 7201 PetscErrorCode ierr; 7202 7203 PetscFunctionBegin; 7204 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 7205 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 7206 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 7207 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 7208 /* Mark ghost points with negative dof */ 7209 for (p = pStart; p < pEnd; ++p) { 7210 PetscInt value; 7211 7212 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 7213 if (value != labelValue) continue; 7214 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 7215 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 7216 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 7217 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 7218 neg[p-pStart] = -(dof+1); 7219 } 7220 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 7221 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 7222 if (nroots >= 0) { 7223 if (nroots > pEnd - pStart) { 7224 PetscInt *tmpDof; 7225 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 7226 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 7227 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 7228 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 7229 for (p = pStart; p < pEnd; ++p) { 7230 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 7231 } 7232 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 7233 } else { 7234 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 7235 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 7236 } 7237 } 7238 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 7239 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7240 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 7241 7242 (*gsection)->atlasOff[p] = off; 7243 7244 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 7245 } 7246 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 7247 globalOff -= off; 7248 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7249 (*gsection)->atlasOff[p] += globalOff; 7250 7251 neg[p] = -((*gsection)->atlasOff[p]+1); 7252 } 7253 /* Put in negative offsets for ghost points */ 7254 if (nroots >= 0) { 7255 if (nroots > pEnd - pStart) { 7256 PetscInt *tmpOff; 7257 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 7258 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 7259 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 7260 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 7261 for (p = pStart; p < pEnd; ++p) { 7262 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 7263 } 7264 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 7265 } else { 7266 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 7267 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 7268 } 7269 } 7270 ierr = PetscFree(neg);CHKERRQ(ierr); 7271 PetscFunctionReturn(0); 7272 } 7273