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 if (!numVertices) { 2411 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2412 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2413 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2414 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2415 PetscFunctionReturn(0); 2416 } 2417 nparts = commSize; 2418 options[0] = 0; /* Use all defaults */ 2419 /* Calculate vertex distribution */ 2420 ierr = PetscMalloc4(nparts+1,PetscInt,&vtxdist,nparts*ncon,PetscReal,&tpwgts,ncon,PetscReal,&ubvec,nvtxs,PetscInt,&assignment);CHKERRQ(ierr); 2421 vtxdist[0] = 0; 2422 ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 2423 for (p = 2; p <= nparts; ++p) { 2424 vtxdist[p] += vtxdist[p-1]; 2425 } 2426 /* Calculate weights */ 2427 for (p = 0; p < nparts; ++p) { 2428 tpwgts[p] = 1.0/nparts; 2429 } 2430 ubvec[0] = 1.05; 2431 2432 if (nparts == 1) { 2433 ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt)); 2434 } else { 2435 if (vtxdist[1] == vtxdist[nparts]) { 2436 if (!rank) { 2437 PetscStackCallStandard(METIS_PartGraphKway, (&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment)); 2438 } 2439 } else { 2440 PetscStackCallStandard(ParMETIS_V3_PartKway, (vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm)); 2441 } 2442 } 2443 /* Convert to PetscSection+IS */ 2444 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2445 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2446 for (v = 0; v < nvtxs; ++v) { 2447 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2448 } 2449 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2450 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2451 for (p = 0, i = 0; p < commSize; ++p) { 2452 for (v = 0; v < nvtxs; ++v) { 2453 if (assignment[v] == p) points[i++] = v; 2454 } 2455 } 2456 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2457 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2458 ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 2459 PetscFunctionReturn(0); 2460 } 2461 #endif 2462 2463 #undef __FUNCT__ 2464 #define __FUNCT__ "DMPlexEnlargePartition" 2465 /* Expand the partition by BFS on the adjacency graph */ 2466 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2467 { 2468 PetscHashI h; 2469 const PetscInt *points; 2470 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2471 PetscInt pStart, pEnd, part, q; 2472 PetscErrorCode ierr; 2473 2474 PetscFunctionBegin; 2475 PetscHashICreate(h); 2476 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2477 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2478 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2479 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2480 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2481 for (part = pStart; part < pEnd; ++part) { 2482 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2483 2484 PetscHashIClear(h); 2485 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2486 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2487 /* Add all existing points to h */ 2488 for (p = 0; p < numPoints; ++p) { 2489 const PetscInt point = points[off+p]; 2490 PetscHashIAdd(h, point, 1); 2491 } 2492 PetscHashISize(h, nP); 2493 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2494 /* Add all points in next BFS level */ 2495 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2496 for (p = 0; p < numPoints; ++p) { 2497 const PetscInt point = points[off+p]; 2498 PetscInt s = start[point], e = start[point+1], a; 2499 2500 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2501 } 2502 PetscHashISize(h, numNewPoints); 2503 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2504 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2505 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2506 totPoints += numNewPoints; 2507 } 2508 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2509 PetscHashIDestroy(h); 2510 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2511 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2512 for (part = pStart, q = 0; part < pEnd; ++part) { 2513 PetscInt numPoints, p; 2514 2515 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2516 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2517 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2518 } 2519 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2520 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2521 PetscFunctionReturn(0); 2522 } 2523 2524 #undef __FUNCT__ 2525 #define __FUNCT__ "DMPlexCreatePartition" 2526 /* 2527 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2528 2529 Collective on DM 2530 2531 Input Parameters: 2532 + dm - The DM 2533 . height - The height for points in the partition 2534 - enlarge - Expand each partition with neighbors 2535 2536 Output Parameters: 2537 + partSection - The PetscSection giving the division of points by partition 2538 . partition - The list of points by partition 2539 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2540 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2541 2542 Level: developer 2543 2544 .seealso DMPlexDistribute() 2545 */ 2546 PetscErrorCode DMPlexCreatePartition(DM dm, const char name[], PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2547 { 2548 char partname[1024]; 2549 PetscBool isChaco = PETSC_FALSE, isMetis = PETSC_FALSE, flg; 2550 PetscMPIInt size; 2551 PetscErrorCode ierr; 2552 2553 PetscFunctionBegin; 2554 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2555 2556 *origPartSection = NULL; 2557 *origPartition = NULL; 2558 if (size == 1) { 2559 PetscInt *points; 2560 PetscInt cStart, cEnd, c; 2561 2562 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2563 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2564 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2565 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2566 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2567 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2568 for (c = cStart; c < cEnd; ++c) points[c] = c; 2569 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2570 PetscFunctionReturn(0); 2571 } 2572 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_partitioner", partname, 1024, &flg);CHKERRQ(ierr); 2573 if (flg) name = partname; 2574 if (name) { 2575 ierr = PetscStrcmp(name, "chaco", &isChaco);CHKERRQ(ierr); 2576 ierr = PetscStrcmp(name, "metis", &isMetis);CHKERRQ(ierr); 2577 } 2578 if (height == 0) { 2579 PetscInt numVertices; 2580 PetscInt *start = NULL; 2581 PetscInt *adjacency = NULL; 2582 2583 ierr = DMPlexCreateNeighborCSR(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2584 if (!name || isChaco) { 2585 #if defined(PETSC_HAVE_CHACO) 2586 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2587 #else 2588 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 2589 #endif 2590 } else if (isMetis) { 2591 #if defined(PETSC_HAVE_PARMETIS) 2592 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2593 #endif 2594 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Unknown mesh partitioning package %s", name); 2595 if (enlarge) { 2596 *origPartSection = *partSection; 2597 *origPartition = *partition; 2598 2599 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2600 } 2601 ierr = PetscFree(start);CHKERRQ(ierr); 2602 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2603 # if 0 2604 } else if (height == 1) { 2605 /* Build the dual graph for faces and partition the hypergraph */ 2606 PetscInt numEdges; 2607 2608 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2609 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2610 destroyCSR(numEdges, start, adjacency); 2611 #endif 2612 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2613 PetscFunctionReturn(0); 2614 } 2615 2616 #undef __FUNCT__ 2617 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2618 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2619 { 2620 /* const PetscInt height = 0; */ 2621 const PetscInt *partArray; 2622 PetscInt *allPoints, *packPoints; 2623 PetscInt rStart, rEnd, rank, pStart, pEnd, newSize; 2624 PetscErrorCode ierr; 2625 PetscBT bt; 2626 PetscSegBuffer segpack,segpart; 2627 2628 PetscFunctionBegin; 2629 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2630 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2631 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2632 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2633 ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 2634 ierr = PetscBTCreate(pEnd-pStart,&bt);CHKERRQ(ierr); 2635 ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpack);CHKERRQ(ierr); 2636 ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpart);CHKERRQ(ierr); 2637 for (rank = rStart; rank < rEnd; ++rank) { 2638 PetscInt partSize = 0, numPoints, offset, p, *PETSC_RESTRICT placePoints; 2639 2640 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2641 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2642 for (p = 0; p < numPoints; ++p) { 2643 PetscInt point = partArray[offset+p], closureSize, c; 2644 PetscInt *closure = NULL; 2645 2646 /* TODO Include support for height > 0 case */ 2647 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2648 for (c=0; c<closureSize; c++) { 2649 PetscInt cpoint = closure[c*2]; 2650 if (!PetscBTLookupSet(bt,cpoint-pStart)) { 2651 PetscInt *PETSC_RESTRICT pt; 2652 partSize++; 2653 ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 2654 *pt = cpoint; 2655 } 2656 } 2657 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2658 } 2659 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 2660 ierr = PetscSegBufferGetInts(segpack,partSize,&placePoints);CHKERRQ(ierr); 2661 ierr = PetscSegBufferExtractTo(segpart,placePoints);CHKERRQ(ierr); 2662 ierr = PetscSortInt(partSize,placePoints);CHKERRQ(ierr); 2663 for (p=0; p<partSize; p++) {ierr = PetscBTClear(bt,placePoints[p]-pStart);CHKERRQ(ierr);} 2664 } 2665 ierr = PetscBTDestroy(&bt);CHKERRQ(ierr); 2666 ierr = PetscSegBufferDestroy(&segpart);CHKERRQ(ierr); 2667 2668 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 2669 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 2670 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 2671 2672 ierr = PetscSegBufferExtractInPlace(segpack,&packPoints);CHKERRQ(ierr); 2673 for (rank = rStart; rank < rEnd; ++rank) { 2674 PetscInt numPoints, offset; 2675 2676 ierr = PetscSectionGetDof(*section, rank, &numPoints);CHKERRQ(ierr); 2677 ierr = PetscSectionGetOffset(*section, rank, &offset);CHKERRQ(ierr); 2678 ierr = PetscMemcpy(&allPoints[offset], packPoints, numPoints * sizeof(PetscInt));CHKERRQ(ierr); 2679 packPoints += numPoints; 2680 } 2681 2682 ierr = PetscSegBufferDestroy(&segpack);CHKERRQ(ierr); 2683 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 2684 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2685 PetscFunctionReturn(0); 2686 } 2687 2688 #undef __FUNCT__ 2689 #define __FUNCT__ "DMPlexDistributeField" 2690 /* 2691 Input Parameters: 2692 . originalSection 2693 , originalVec 2694 2695 Output Parameters: 2696 . newSection 2697 . newVec 2698 */ 2699 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 2700 { 2701 PetscSF fieldSF; 2702 PetscInt *remoteOffsets, fieldSize; 2703 PetscScalar *originalValues, *newValues; 2704 PetscErrorCode ierr; 2705 2706 PetscFunctionBegin; 2707 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 2708 2709 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 2710 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 2711 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 2712 2713 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 2714 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 2715 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 2716 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 2717 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 2718 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 2719 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 2720 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 2721 PetscFunctionReturn(0); 2722 } 2723 2724 #undef __FUNCT__ 2725 #define __FUNCT__ "DMPlexDistribute" 2726 /*@C 2727 DMPlexDistribute - Distributes the mesh and any associated sections. 2728 2729 Not Collective 2730 2731 Input Parameter: 2732 + dm - The original DMPlex object 2733 . partitioner - The partitioning package, or NULL for the default 2734 - overlap - The overlap of partitions, 0 is the default 2735 2736 Output Parameter: 2737 . parallelMesh - The distributed DMPlex object, or NULL 2738 2739 Note: If the mesh was not distributed, the return value is NULL 2740 2741 Level: intermediate 2742 2743 .keywords: mesh, elements 2744 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 2745 @*/ 2746 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 2747 { 2748 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 2749 MPI_Comm comm; 2750 const PetscInt height = 0; 2751 PetscInt dim, numRemoteRanks; 2752 IS origCellPart, cellPart, part; 2753 PetscSection origCellPartSection, cellPartSection, partSection; 2754 PetscSFNode *remoteRanks; 2755 PetscSF partSF, pointSF, coneSF; 2756 ISLocalToGlobalMapping renumbering; 2757 PetscSection originalConeSection, newConeSection; 2758 PetscInt *remoteOffsets; 2759 PetscInt *cones, *newCones, newConesSize; 2760 PetscBool flg; 2761 PetscMPIInt rank, numProcs, p; 2762 PetscErrorCode ierr; 2763 2764 PetscFunctionBegin; 2765 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2766 PetscValidPointer(dmParallel,4); 2767 2768 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 2769 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2770 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2771 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 2772 2773 *dmParallel = NULL; 2774 if (numProcs == 1) PetscFunctionReturn(0); 2775 2776 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2777 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 2778 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 2779 ierr = DMPlexCreatePartition(dm, partitioner, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 2780 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 2781 if (!rank) numRemoteRanks = numProcs; 2782 else numRemoteRanks = 0; 2783 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 2784 for (p = 0; p < numRemoteRanks; ++p) { 2785 remoteRanks[p].rank = p; 2786 remoteRanks[p].index = 0; 2787 } 2788 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 2789 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 2790 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 2791 if (flg) { 2792 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 2793 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2794 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 2795 if (origCellPart) { 2796 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 2797 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2798 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 2799 } 2800 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 2801 } 2802 /* Close the partition over the mesh */ 2803 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 2804 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 2805 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 2806 /* Create new mesh */ 2807 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 2808 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 2809 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 2810 pmesh = (DM_Plex*) (*dmParallel)->data; 2811 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 2812 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 2813 if (flg) { 2814 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 2815 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2816 ierr = ISView(part, NULL);CHKERRQ(ierr); 2817 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 2818 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 2819 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 2820 } 2821 /* Distribute cone section */ 2822 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 2823 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 2824 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 2825 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 2826 { 2827 PetscInt pStart, pEnd, p; 2828 2829 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 2830 for (p = pStart; p < pEnd; ++p) { 2831 PetscInt coneSize; 2832 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 2833 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 2834 } 2835 } 2836 /* Communicate and renumber cones */ 2837 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 2838 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2839 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 2840 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2841 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2842 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 2843 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 2844 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 2845 if (flg) { 2846 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 2847 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2848 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 2849 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2850 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 2851 } 2852 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 2853 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 2854 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2855 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2856 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 2857 /* Create supports and stratify sieve */ 2858 { 2859 PetscInt pStart, pEnd; 2860 2861 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2862 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2863 } 2864 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 2865 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 2866 /* Distribute Coordinates */ 2867 { 2868 PetscSection originalCoordSection, newCoordSection; 2869 Vec originalCoordinates, newCoordinates; 2870 const char *name; 2871 2872 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 2873 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 2874 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 2875 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 2876 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 2877 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 2878 2879 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 2880 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 2881 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 2882 } 2883 /* Distribute labels */ 2884 { 2885 DMLabel next = mesh->labels, newNext = pmesh->labels; 2886 PetscInt numLabels = 0, l; 2887 2888 /* Bcast number of labels */ 2889 while (next) { 2890 ++numLabels; next = next->next; 2891 } 2892 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 2893 next = mesh->labels; 2894 for (l = 0; l < numLabels; ++l) { 2895 DMLabel newLabel; 2896 const PetscInt *partArray; 2897 char *name; 2898 PetscInt *stratumSizes = NULL, *points = NULL; 2899 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 2900 PetscInt nameSize, s, p; 2901 PetscBool isdepth; 2902 size_t len = 0; 2903 2904 /* Bcast name (could filter for no points) */ 2905 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 2906 nameSize = len; 2907 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 2908 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 2909 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 2910 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 2911 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 2912 if (isdepth) { /* skip because "depth" is not distributed */ 2913 ierr = PetscFree(name);CHKERRQ(ierr); 2914 if (!rank) next = next->next; 2915 continue; 2916 } 2917 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 2918 newLabel->name = name; 2919 /* Bcast numStrata (could filter for no points in stratum) */ 2920 if (!rank) newLabel->numStrata = next->numStrata; 2921 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 2922 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 2923 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 2924 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 2925 /* Bcast stratumValues (could filter for no points in stratum) */ 2926 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 2927 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 2928 /* Find size on each process and Scatter */ 2929 if (!rank) { 2930 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 2931 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 2932 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 2933 for (s = 0; s < next->numStrata; ++s) { 2934 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 2935 const PetscInt point = next->points[p]; 2936 PetscInt proc; 2937 2938 for (proc = 0; proc < numProcs; ++proc) { 2939 PetscInt dof, off, pPart; 2940 2941 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 2942 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 2943 for (pPart = off; pPart < off+dof; ++pPart) { 2944 if (partArray[pPart] == point) { 2945 ++stratumSizes[proc*next->numStrata+s]; 2946 break; 2947 } 2948 } 2949 } 2950 } 2951 } 2952 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 2953 } 2954 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 2955 /* Calculate stratumOffsets */ 2956 newLabel->stratumOffsets[0] = 0; 2957 for (s = 0; s < newLabel->numStrata; ++s) { 2958 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 2959 } 2960 /* Pack points and Scatter */ 2961 if (!rank) { 2962 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 2963 displs[0] = 0; 2964 for (p = 0; p < numProcs; ++p) { 2965 sendcnts[p] = 0; 2966 for (s = 0; s < next->numStrata; ++s) { 2967 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 2968 } 2969 offsets[p] = displs[p]; 2970 displs[p+1] = displs[p] + sendcnts[p]; 2971 } 2972 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 2973 for (s = 0; s < next->numStrata; ++s) { 2974 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 2975 const PetscInt point = next->points[p]; 2976 PetscInt proc; 2977 2978 for (proc = 0; proc < numProcs; ++proc) { 2979 PetscInt dof, off, pPart; 2980 2981 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 2982 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 2983 for (pPart = off; pPart < off+dof; ++pPart) { 2984 if (partArray[pPart] == point) { 2985 points[offsets[proc]++] = point; 2986 break; 2987 } 2988 } 2989 } 2990 } 2991 } 2992 } 2993 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 2994 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 2995 ierr = PetscFree(points);CHKERRQ(ierr); 2996 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 2997 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 2998 /* Renumber points */ 2999 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3000 /* Sort points */ 3001 for (s = 0; s < newLabel->numStrata; ++s) { 3002 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3003 } 3004 /* Insert into list */ 3005 if (newNext) newNext->next = newLabel; 3006 else pmesh->labels = newLabel; 3007 newNext = newLabel; 3008 if (!rank) next = next->next; 3009 } 3010 } 3011 /* Cleanup Partition */ 3012 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3013 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3014 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3015 ierr = ISDestroy(&part);CHKERRQ(ierr); 3016 /* Create point SF for parallel mesh */ 3017 { 3018 const PetscInt *leaves; 3019 PetscSFNode *remotePoints, *rowners, *lowners; 3020 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3021 PetscInt pStart, pEnd; 3022 3023 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3024 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3025 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3026 for (p=0; p<numRoots; p++) { 3027 rowners[p].rank = -1; 3028 rowners[p].index = -1; 3029 } 3030 if (origCellPart) { 3031 /* Make sure cells in the original partition are not assigned to other procs */ 3032 const PetscInt *origCells; 3033 3034 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3035 for (p = 0; p < numProcs; ++p) { 3036 PetscInt dof, off, d; 3037 3038 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3039 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3040 for (d = off; d < off+dof; ++d) { 3041 rowners[origCells[d]].rank = p; 3042 } 3043 } 3044 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3045 } 3046 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3047 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3048 3049 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3050 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3051 for (p = 0; p < numLeaves; ++p) { 3052 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3053 lowners[p].rank = rank; 3054 lowners[p].index = leaves ? leaves[p] : p; 3055 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3056 lowners[p].rank = -2; 3057 lowners[p].index = -2; 3058 } 3059 } 3060 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3061 rowners[p].rank = -3; 3062 rowners[p].index = -3; 3063 } 3064 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3065 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3066 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3067 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3068 for (p = 0; p < numLeaves; ++p) { 3069 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3070 if (lowners[p].rank != rank) ++numGhostPoints; 3071 } 3072 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3073 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3074 for (p = 0, gp = 0; p < numLeaves; ++p) { 3075 if (lowners[p].rank != rank) { 3076 ghostPoints[gp] = leaves ? leaves[p] : p; 3077 remotePoints[gp].rank = lowners[p].rank; 3078 remotePoints[gp].index = lowners[p].index; 3079 ++gp; 3080 } 3081 } 3082 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3083 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3084 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3085 } 3086 /* Cleanup */ 3087 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3088 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3089 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3090 PetscFunctionReturn(0); 3091 } 3092 3093 #undef __FUNCT__ 3094 #define __FUNCT__ "DMPlexInvertCell" 3095 /*@C 3096 DMPlexInvertCell - This flips tetrahedron and hexahedron orientation since Plex stores them internally with outward normals. Other cells are left untouched. 3097 3098 Input Parameters: 3099 + numCorners - The number of vertices in a cell 3100 - cone - The incoming cone 3101 3102 Output Parameter: 3103 . cone - The inverted cone (in-place) 3104 3105 Level: developer 3106 3107 .seealso: DMPlexGenerate() 3108 @*/ 3109 PetscErrorCode DMPlexInvertCell(PetscInt dim, PetscInt numCorners, int cone[]) 3110 { 3111 int tmpc; 3112 3113 PetscFunctionBegin; 3114 if (dim != 3) PetscFunctionReturn(0); 3115 switch (numCorners) { 3116 case 4: 3117 tmpc = cone[0]; 3118 cone[0] = cone[1]; 3119 cone[1] = tmpc; 3120 break; 3121 case 8: 3122 tmpc = cone[1]; 3123 cone[1] = cone[3]; 3124 cone[3] = tmpc; 3125 break; 3126 default: break; 3127 } 3128 PetscFunctionReturn(0); 3129 } 3130 3131 #undef __FUNCT__ 3132 #define __FUNCT__ "DMPlexInvertCells_Internal" 3133 /* This is to fix the tetrahedron orientation from TetGen */ 3134 PETSC_UNUSED static PetscErrorCode DMPlexInvertCells_Internal(PetscInt dim, PetscInt numCells, PetscInt numCorners, int cells[]) 3135 { 3136 PetscInt bound = numCells*numCorners, coff; 3137 PetscErrorCode ierr; 3138 3139 PetscFunctionBegin; 3140 for (coff = 0; coff < bound; coff += numCorners) { 3141 ierr = DMPlexInvertCell(dim, numCorners, &cells[coff]);CHKERRQ(ierr); 3142 } 3143 PetscFunctionReturn(0); 3144 } 3145 3146 #if defined(PETSC_HAVE_TRIANGLE) 3147 #include <triangle.h> 3148 3149 #undef __FUNCT__ 3150 #define __FUNCT__ "InitInput_Triangle" 3151 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 3152 { 3153 PetscFunctionBegin; 3154 inputCtx->numberofpoints = 0; 3155 inputCtx->numberofpointattributes = 0; 3156 inputCtx->pointlist = NULL; 3157 inputCtx->pointattributelist = NULL; 3158 inputCtx->pointmarkerlist = NULL; 3159 inputCtx->numberofsegments = 0; 3160 inputCtx->segmentlist = NULL; 3161 inputCtx->segmentmarkerlist = NULL; 3162 inputCtx->numberoftriangleattributes = 0; 3163 inputCtx->trianglelist = NULL; 3164 inputCtx->numberofholes = 0; 3165 inputCtx->holelist = NULL; 3166 inputCtx->numberofregions = 0; 3167 inputCtx->regionlist = NULL; 3168 PetscFunctionReturn(0); 3169 } 3170 3171 #undef __FUNCT__ 3172 #define __FUNCT__ "InitOutput_Triangle" 3173 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 3174 { 3175 PetscFunctionBegin; 3176 outputCtx->numberofpoints = 0; 3177 outputCtx->pointlist = NULL; 3178 outputCtx->pointattributelist = NULL; 3179 outputCtx->pointmarkerlist = NULL; 3180 outputCtx->numberoftriangles = 0; 3181 outputCtx->trianglelist = NULL; 3182 outputCtx->triangleattributelist = NULL; 3183 outputCtx->neighborlist = NULL; 3184 outputCtx->segmentlist = NULL; 3185 outputCtx->segmentmarkerlist = NULL; 3186 outputCtx->numberofedges = 0; 3187 outputCtx->edgelist = NULL; 3188 outputCtx->edgemarkerlist = NULL; 3189 PetscFunctionReturn(0); 3190 } 3191 3192 #undef __FUNCT__ 3193 #define __FUNCT__ "FiniOutput_Triangle" 3194 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 3195 { 3196 PetscFunctionBegin; 3197 free(outputCtx->pointmarkerlist); 3198 free(outputCtx->edgelist); 3199 free(outputCtx->edgemarkerlist); 3200 free(outputCtx->trianglelist); 3201 free(outputCtx->neighborlist); 3202 PetscFunctionReturn(0); 3203 } 3204 3205 #undef __FUNCT__ 3206 #define __FUNCT__ "DMPlexGenerate_Triangle" 3207 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 3208 { 3209 MPI_Comm comm; 3210 PetscInt dim = 2; 3211 const PetscBool createConvexHull = PETSC_FALSE; 3212 const PetscBool constrained = PETSC_FALSE; 3213 struct triangulateio in; 3214 struct triangulateio out; 3215 PetscInt vStart, vEnd, v, eStart, eEnd, e; 3216 PetscMPIInt rank; 3217 PetscErrorCode ierr; 3218 3219 PetscFunctionBegin; 3220 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3221 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3222 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 3223 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 3224 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3225 3226 in.numberofpoints = vEnd - vStart; 3227 if (in.numberofpoints > 0) { 3228 PetscSection coordSection; 3229 Vec coordinates; 3230 PetscScalar *array; 3231 3232 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 3233 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 3234 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3235 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3236 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3237 for (v = vStart; v < vEnd; ++v) { 3238 const PetscInt idx = v - vStart; 3239 PetscInt off, d; 3240 3241 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3242 for (d = 0; d < dim; ++d) { 3243 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3244 } 3245 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3246 } 3247 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3248 } 3249 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 3250 in.numberofsegments = eEnd - eStart; 3251 if (in.numberofsegments > 0) { 3252 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 3253 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 3254 for (e = eStart; e < eEnd; ++e) { 3255 const PetscInt idx = e - eStart; 3256 const PetscInt *cone; 3257 3258 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 3259 3260 in.segmentlist[idx*2+0] = cone[0] - vStart; 3261 in.segmentlist[idx*2+1] = cone[1] - vStart; 3262 3263 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 3264 } 3265 } 3266 #if 0 /* Do not currently support holes */ 3267 PetscReal *holeCoords; 3268 PetscInt h, d; 3269 3270 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 3271 if (in.numberofholes > 0) { 3272 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 3273 for (h = 0; h < in.numberofholes; ++h) { 3274 for (d = 0; d < dim; ++d) { 3275 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 3276 } 3277 } 3278 } 3279 #endif 3280 if (!rank) { 3281 char args[32]; 3282 3283 /* Take away 'Q' for verbose output */ 3284 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 3285 if (createConvexHull) { 3286 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 3287 } 3288 if (constrained) { 3289 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 3290 } 3291 triangulate(args, &in, &out, NULL); 3292 } 3293 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 3294 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 3295 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 3296 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 3297 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 3298 3299 { 3300 const PetscInt numCorners = 3; 3301 const PetscInt numCells = out.numberoftriangles; 3302 const PetscInt numVertices = out.numberofpoints; 3303 const int *cells = out.trianglelist; 3304 const double *meshCoords = out.pointlist; 3305 3306 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3307 /* Set labels */ 3308 for (v = 0; v < numVertices; ++v) { 3309 if (out.pointmarkerlist[v]) { 3310 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3311 } 3312 } 3313 if (interpolate) { 3314 for (e = 0; e < out.numberofedges; e++) { 3315 if (out.edgemarkerlist[e]) { 3316 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3317 const PetscInt *edges; 3318 PetscInt numEdges; 3319 3320 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3321 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3322 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3323 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3324 } 3325 } 3326 } 3327 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3328 } 3329 #if 0 /* Do not currently support holes */ 3330 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 3331 #endif 3332 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 3333 PetscFunctionReturn(0); 3334 } 3335 3336 #undef __FUNCT__ 3337 #define __FUNCT__ "DMPlexRefine_Triangle" 3338 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 3339 { 3340 MPI_Comm comm; 3341 PetscInt dim = 2; 3342 struct triangulateio in; 3343 struct triangulateio out; 3344 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3345 PetscMPIInt rank; 3346 PetscErrorCode ierr; 3347 3348 PetscFunctionBegin; 3349 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3350 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3351 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 3352 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 3353 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3354 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3355 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3356 3357 in.numberofpoints = vEnd - vStart; 3358 if (in.numberofpoints > 0) { 3359 PetscSection coordSection; 3360 Vec coordinates; 3361 PetscScalar *array; 3362 3363 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 3364 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 3365 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3366 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3367 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3368 for (v = vStart; v < vEnd; ++v) { 3369 const PetscInt idx = v - vStart; 3370 PetscInt off, d; 3371 3372 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3373 for (d = 0; d < dim; ++d) { 3374 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3375 } 3376 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3377 } 3378 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3379 } 3380 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3381 3382 in.numberofcorners = 3; 3383 in.numberoftriangles = cEnd - cStart; 3384 3385 in.trianglearealist = (double*) maxVolumes; 3386 if (in.numberoftriangles > 0) { 3387 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 3388 for (c = cStart; c < cEnd; ++c) { 3389 const PetscInt idx = c - cStart; 3390 PetscInt *closure = NULL; 3391 PetscInt closureSize; 3392 3393 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3394 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 3395 for (v = 0; v < 3; ++v) { 3396 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 3397 } 3398 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3399 } 3400 } 3401 /* TODO: Segment markers are missing on input */ 3402 #if 0 /* Do not currently support holes */ 3403 PetscReal *holeCoords; 3404 PetscInt h, d; 3405 3406 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 3407 if (in.numberofholes > 0) { 3408 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 3409 for (h = 0; h < in.numberofholes; ++h) { 3410 for (d = 0; d < dim; ++d) { 3411 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 3412 } 3413 } 3414 } 3415 #endif 3416 if (!rank) { 3417 char args[32]; 3418 3419 /* Take away 'Q' for verbose output */ 3420 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 3421 triangulate(args, &in, &out, NULL); 3422 } 3423 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 3424 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 3425 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 3426 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 3427 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 3428 3429 { 3430 const PetscInt numCorners = 3; 3431 const PetscInt numCells = out.numberoftriangles; 3432 const PetscInt numVertices = out.numberofpoints; 3433 const int *cells = out.trianglelist; 3434 const double *meshCoords = out.pointlist; 3435 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3436 3437 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3438 /* Set labels */ 3439 for (v = 0; v < numVertices; ++v) { 3440 if (out.pointmarkerlist[v]) { 3441 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3442 } 3443 } 3444 if (interpolate) { 3445 PetscInt e; 3446 3447 for (e = 0; e < out.numberofedges; e++) { 3448 if (out.edgemarkerlist[e]) { 3449 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3450 const PetscInt *edges; 3451 PetscInt numEdges; 3452 3453 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3454 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3455 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3456 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3457 } 3458 } 3459 } 3460 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3461 } 3462 #if 0 /* Do not currently support holes */ 3463 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 3464 #endif 3465 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 3466 PetscFunctionReturn(0); 3467 } 3468 #endif 3469 3470 #if defined(PETSC_HAVE_TETGEN) 3471 #include <tetgen.h> 3472 #undef __FUNCT__ 3473 #define __FUNCT__ "DMPlexGenerate_Tetgen" 3474 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 3475 { 3476 MPI_Comm comm; 3477 const PetscInt dim = 3; 3478 ::tetgenio in; 3479 ::tetgenio out; 3480 PetscInt vStart, vEnd, v, fStart, fEnd, f; 3481 PetscMPIInt rank; 3482 PetscErrorCode ierr; 3483 3484 PetscFunctionBegin; 3485 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3486 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3487 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3488 in.numberofpoints = vEnd - vStart; 3489 if (in.numberofpoints > 0) { 3490 PetscSection coordSection; 3491 Vec coordinates; 3492 PetscScalar *array; 3493 3494 in.pointlist = new double[in.numberofpoints*dim]; 3495 in.pointmarkerlist = new int[in.numberofpoints]; 3496 3497 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3498 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3499 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3500 for (v = vStart; v < vEnd; ++v) { 3501 const PetscInt idx = v - vStart; 3502 PetscInt off, d; 3503 3504 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3505 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 3506 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3507 } 3508 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3509 } 3510 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 3511 3512 in.numberoffacets = fEnd - fStart; 3513 if (in.numberoffacets > 0) { 3514 in.facetlist = new tetgenio::facet[in.numberoffacets]; 3515 in.facetmarkerlist = new int[in.numberoffacets]; 3516 for (f = fStart; f < fEnd; ++f) { 3517 const PetscInt idx = f - fStart; 3518 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 3519 3520 in.facetlist[idx].numberofpolygons = 1; 3521 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 3522 in.facetlist[idx].numberofholes = 0; 3523 in.facetlist[idx].holelist = NULL; 3524 3525 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3526 for (p = 0; p < numPoints*2; p += 2) { 3527 const PetscInt point = points[p]; 3528 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 3529 } 3530 3531 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 3532 poly->numberofvertices = numVertices; 3533 poly->vertexlist = new int[poly->numberofvertices]; 3534 for (v = 0; v < numVertices; ++v) { 3535 const PetscInt vIdx = points[v] - vStart; 3536 poly->vertexlist[v] = vIdx; 3537 } 3538 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 3539 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3540 } 3541 } 3542 if (!rank) { 3543 char args[32]; 3544 3545 /* Take away 'Q' for verbose output */ 3546 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 3547 ::tetrahedralize(args, &in, &out); 3548 } 3549 { 3550 const PetscInt numCorners = 4; 3551 const PetscInt numCells = out.numberoftetrahedra; 3552 const PetscInt numVertices = out.numberofpoints; 3553 const double *meshCoords = out.pointlist; 3554 int *cells = out.tetrahedronlist; 3555 3556 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3557 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3558 /* Set labels */ 3559 for (v = 0; v < numVertices; ++v) { 3560 if (out.pointmarkerlist[v]) { 3561 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3562 } 3563 } 3564 if (interpolate) { 3565 PetscInt e; 3566 3567 for (e = 0; e < out.numberofedges; e++) { 3568 if (out.edgemarkerlist[e]) { 3569 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3570 const PetscInt *edges; 3571 PetscInt numEdges; 3572 3573 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3574 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3575 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3576 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3577 } 3578 } 3579 for (f = 0; f < out.numberoftrifaces; f++) { 3580 if (out.trifacemarkerlist[f]) { 3581 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 3582 const PetscInt *faces; 3583 PetscInt numFaces; 3584 3585 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3586 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3587 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 3588 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3589 } 3590 } 3591 } 3592 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3593 } 3594 PetscFunctionReturn(0); 3595 } 3596 3597 #undef __FUNCT__ 3598 #define __FUNCT__ "DMPlexRefine_Tetgen" 3599 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 3600 { 3601 MPI_Comm comm; 3602 const PetscInt dim = 3; 3603 ::tetgenio in; 3604 ::tetgenio out; 3605 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3606 PetscMPIInt rank; 3607 PetscErrorCode ierr; 3608 3609 PetscFunctionBegin; 3610 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3611 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3612 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3613 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3614 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3615 3616 in.numberofpoints = vEnd - vStart; 3617 if (in.numberofpoints > 0) { 3618 PetscSection coordSection; 3619 Vec coordinates; 3620 PetscScalar *array; 3621 3622 in.pointlist = new double[in.numberofpoints*dim]; 3623 in.pointmarkerlist = new int[in.numberofpoints]; 3624 3625 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3626 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3627 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3628 for (v = vStart; v < vEnd; ++v) { 3629 const PetscInt idx = v - vStart; 3630 PetscInt off, d; 3631 3632 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3633 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 3634 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3635 } 3636 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3637 } 3638 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3639 3640 in.numberofcorners = 4; 3641 in.numberoftetrahedra = cEnd - cStart; 3642 in.tetrahedronvolumelist = (double*) maxVolumes; 3643 if (in.numberoftetrahedra > 0) { 3644 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 3645 for (c = cStart; c < cEnd; ++c) { 3646 const PetscInt idx = c - cStart; 3647 PetscInt *closure = NULL; 3648 PetscInt closureSize; 3649 3650 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3651 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 3652 for (v = 0; v < 4; ++v) { 3653 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 3654 } 3655 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3656 } 3657 } 3658 /* TODO: Put in boundary faces with markers */ 3659 if (!rank) { 3660 char args[32]; 3661 3662 /* Take away 'Q' for verbose output */ 3663 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 3664 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 3665 ::tetrahedralize(args, &in, &out); 3666 } 3667 in.tetrahedronvolumelist = NULL; 3668 3669 { 3670 const PetscInt numCorners = 4; 3671 const PetscInt numCells = out.numberoftetrahedra; 3672 const PetscInt numVertices = out.numberofpoints; 3673 const double *meshCoords = out.pointlist; 3674 int *cells = out.tetrahedronlist; 3675 3676 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3677 3678 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3679 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3680 /* Set labels */ 3681 for (v = 0; v < numVertices; ++v) { 3682 if (out.pointmarkerlist[v]) { 3683 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3684 } 3685 } 3686 if (interpolate) { 3687 PetscInt e, f; 3688 3689 for (e = 0; e < out.numberofedges; e++) { 3690 if (out.edgemarkerlist[e]) { 3691 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3692 const PetscInt *edges; 3693 PetscInt numEdges; 3694 3695 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3696 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3697 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3698 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3699 } 3700 } 3701 for (f = 0; f < out.numberoftrifaces; f++) { 3702 if (out.trifacemarkerlist[f]) { 3703 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 3704 const PetscInt *faces; 3705 PetscInt numFaces; 3706 3707 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3708 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3709 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 3710 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3711 } 3712 } 3713 } 3714 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3715 } 3716 PetscFunctionReturn(0); 3717 } 3718 #endif 3719 3720 #if defined(PETSC_HAVE_CTETGEN) 3721 #include "ctetgen.h" 3722 3723 #undef __FUNCT__ 3724 #define __FUNCT__ "DMPlexGenerate_CTetgen" 3725 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 3726 { 3727 MPI_Comm comm; 3728 const PetscInt dim = 3; 3729 PLC *in, *out; 3730 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 3731 PetscMPIInt rank; 3732 PetscErrorCode ierr; 3733 3734 PetscFunctionBegin; 3735 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3736 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3737 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3738 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3739 ierr = PLCCreate(&in);CHKERRQ(ierr); 3740 ierr = PLCCreate(&out);CHKERRQ(ierr); 3741 3742 in->numberofpoints = vEnd - vStart; 3743 if (in->numberofpoints > 0) { 3744 PetscSection coordSection; 3745 Vec coordinates; 3746 PetscScalar *array; 3747 3748 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 3749 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 3750 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3751 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3752 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3753 for (v = vStart; v < vEnd; ++v) { 3754 const PetscInt idx = v - vStart; 3755 PetscInt off, d, m; 3756 3757 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3758 for (d = 0; d < dim; ++d) { 3759 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3760 } 3761 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 3762 3763 in->pointmarkerlist[idx] = (int) m; 3764 } 3765 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3766 } 3767 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 3768 3769 in->numberoffacets = fEnd - fStart; 3770 if (in->numberoffacets > 0) { 3771 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 3772 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 3773 for (f = fStart; f < fEnd; ++f) { 3774 const PetscInt idx = f - fStart; 3775 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 3776 polygon *poly; 3777 3778 in->facetlist[idx].numberofpolygons = 1; 3779 3780 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 3781 3782 in->facetlist[idx].numberofholes = 0; 3783 in->facetlist[idx].holelist = NULL; 3784 3785 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3786 for (p = 0; p < numPoints*2; p += 2) { 3787 const PetscInt point = points[p]; 3788 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 3789 } 3790 3791 poly = in->facetlist[idx].polygonlist; 3792 poly->numberofvertices = numVertices; 3793 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 3794 for (v = 0; v < numVertices; ++v) { 3795 const PetscInt vIdx = points[v] - vStart; 3796 poly->vertexlist[v] = vIdx; 3797 } 3798 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 3799 in->facetmarkerlist[idx] = (int) m; 3800 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3801 } 3802 } 3803 if (!rank) { 3804 TetGenOpts t; 3805 3806 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3807 t.in = boundary; /* Should go away */ 3808 t.plc = 1; 3809 t.quality = 1; 3810 t.edgesout = 1; 3811 t.zeroindex = 1; 3812 t.quiet = 1; 3813 t.verbose = verbose; 3814 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3815 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3816 } 3817 { 3818 const PetscInt numCorners = 4; 3819 const PetscInt numCells = out->numberoftetrahedra; 3820 const PetscInt numVertices = out->numberofpoints; 3821 const double *meshCoords = out->pointlist; 3822 int *cells = out->tetrahedronlist; 3823 3824 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3825 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3826 /* Set labels */ 3827 for (v = 0; v < numVertices; ++v) { 3828 if (out->pointmarkerlist[v]) { 3829 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 3830 } 3831 } 3832 if (interpolate) { 3833 PetscInt e; 3834 3835 for (e = 0; e < out->numberofedges; e++) { 3836 if (out->edgemarkerlist[e]) { 3837 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 3838 const PetscInt *edges; 3839 PetscInt numEdges; 3840 3841 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3842 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3843 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 3844 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3845 } 3846 } 3847 for (f = 0; f < out->numberoftrifaces; f++) { 3848 if (out->trifacemarkerlist[f]) { 3849 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 3850 const PetscInt *faces; 3851 PetscInt numFaces; 3852 3853 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3854 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3855 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 3856 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3857 } 3858 } 3859 } 3860 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3861 } 3862 3863 ierr = PLCDestroy(&in);CHKERRQ(ierr); 3864 ierr = PLCDestroy(&out);CHKERRQ(ierr); 3865 PetscFunctionReturn(0); 3866 } 3867 3868 #undef __FUNCT__ 3869 #define __FUNCT__ "DMPlexRefine_CTetgen" 3870 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 3871 { 3872 MPI_Comm comm; 3873 const PetscInt dim = 3; 3874 PLC *in, *out; 3875 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3876 PetscMPIInt rank; 3877 PetscErrorCode ierr; 3878 3879 PetscFunctionBegin; 3880 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3881 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3882 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3883 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3884 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3885 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3886 ierr = PLCCreate(&in);CHKERRQ(ierr); 3887 ierr = PLCCreate(&out);CHKERRQ(ierr); 3888 3889 in->numberofpoints = vEnd - vStart; 3890 if (in->numberofpoints > 0) { 3891 PetscSection coordSection; 3892 Vec coordinates; 3893 PetscScalar *array; 3894 3895 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 3896 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 3897 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3898 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3899 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3900 for (v = vStart; v < vEnd; ++v) { 3901 const PetscInt idx = v - vStart; 3902 PetscInt off, d, m; 3903 3904 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3905 for (d = 0; d < dim; ++d) { 3906 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3907 } 3908 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 3909 3910 in->pointmarkerlist[idx] = (int) m; 3911 } 3912 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3913 } 3914 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3915 3916 in->numberofcorners = 4; 3917 in->numberoftetrahedra = cEnd - cStart; 3918 in->tetrahedronvolumelist = maxVolumes; 3919 if (in->numberoftetrahedra > 0) { 3920 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 3921 for (c = cStart; c < cEnd; ++c) { 3922 const PetscInt idx = c - cStart; 3923 PetscInt *closure = NULL; 3924 PetscInt closureSize; 3925 3926 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3927 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 3928 for (v = 0; v < 4; ++v) { 3929 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 3930 } 3931 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3932 } 3933 } 3934 if (!rank) { 3935 TetGenOpts t; 3936 3937 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3938 3939 t.in = dm; /* Should go away */ 3940 t.refine = 1; 3941 t.varvolume = 1; 3942 t.quality = 1; 3943 t.edgesout = 1; 3944 t.zeroindex = 1; 3945 t.quiet = 1; 3946 t.verbose = verbose; /* Change this */ 3947 3948 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3949 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3950 } 3951 { 3952 const PetscInt numCorners = 4; 3953 const PetscInt numCells = out->numberoftetrahedra; 3954 const PetscInt numVertices = out->numberofpoints; 3955 const double *meshCoords = out->pointlist; 3956 int *cells = out->tetrahedronlist; 3957 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3958 3959 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3960 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3961 /* Set labels */ 3962 for (v = 0; v < numVertices; ++v) { 3963 if (out->pointmarkerlist[v]) { 3964 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 3965 } 3966 } 3967 if (interpolate) { 3968 PetscInt e, f; 3969 3970 for (e = 0; e < out->numberofedges; e++) { 3971 if (out->edgemarkerlist[e]) { 3972 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 3973 const PetscInt *edges; 3974 PetscInt numEdges; 3975 3976 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3977 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3978 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 3979 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3980 } 3981 } 3982 for (f = 0; f < out->numberoftrifaces; f++) { 3983 if (out->trifacemarkerlist[f]) { 3984 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 3985 const PetscInt *faces; 3986 PetscInt numFaces; 3987 3988 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3989 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3990 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 3991 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3992 } 3993 } 3994 } 3995 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3996 } 3997 ierr = PLCDestroy(&in);CHKERRQ(ierr); 3998 ierr = PLCDestroy(&out);CHKERRQ(ierr); 3999 PetscFunctionReturn(0); 4000 } 4001 #endif 4002 4003 #undef __FUNCT__ 4004 #define __FUNCT__ "DMPlexGenerate" 4005 /*@C 4006 DMPlexGenerate - Generates a mesh. 4007 4008 Not Collective 4009 4010 Input Parameters: 4011 + boundary - The DMPlex boundary object 4012 . name - The mesh generation package name 4013 - interpolate - Flag to create intermediate mesh elements 4014 4015 Output Parameter: 4016 . mesh - The DMPlex object 4017 4018 Level: intermediate 4019 4020 .keywords: mesh, elements 4021 .seealso: DMPlexCreate(), DMRefine() 4022 @*/ 4023 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 4024 { 4025 PetscInt dim; 4026 char genname[1024]; 4027 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 4028 PetscErrorCode ierr; 4029 4030 PetscFunctionBegin; 4031 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 4032 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 4033 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 4034 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 4035 if (flg) name = genname; 4036 if (name) { 4037 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 4038 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 4039 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 4040 } 4041 switch (dim) { 4042 case 1: 4043 if (!name || isTriangle) { 4044 #if defined(PETSC_HAVE_TRIANGLE) 4045 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 4046 #else 4047 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 4048 #endif 4049 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 4050 break; 4051 case 2: 4052 if (!name || isCTetgen) { 4053 #if defined(PETSC_HAVE_CTETGEN) 4054 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 4055 #else 4056 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 4057 #endif 4058 } else if (isTetgen) { 4059 #if defined(PETSC_HAVE_TETGEN) 4060 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 4061 #else 4062 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 4063 #endif 4064 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 4065 break; 4066 default: 4067 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 4068 } 4069 PetscFunctionReturn(0); 4070 } 4071 4072 typedef PetscInt CellRefiner; 4073 4074 #undef __FUNCT__ 4075 #define __FUNCT__ "GetDepthStart_Private" 4076 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 4077 { 4078 PetscFunctionBegin; 4079 if (cStart) *cStart = 0; 4080 if (vStart) *vStart = depthSize[depth]; 4081 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 4082 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 4083 PetscFunctionReturn(0); 4084 } 4085 4086 #undef __FUNCT__ 4087 #define __FUNCT__ "GetDepthEnd_Private" 4088 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 4089 { 4090 PetscFunctionBegin; 4091 if (cEnd) *cEnd = depthSize[depth]; 4092 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 4093 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 4094 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 4095 PetscFunctionReturn(0); 4096 } 4097 4098 #undef __FUNCT__ 4099 #define __FUNCT__ "CellRefinerGetSizes" 4100 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 4101 { 4102 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 4103 PetscErrorCode ierr; 4104 4105 PetscFunctionBegin; 4106 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4107 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4108 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4109 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4110 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4111 switch (refiner) { 4112 case 1: 4113 /* Simplicial 2D */ 4114 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 4115 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 4116 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 4117 break; 4118 case 3: 4119 /* Hybrid 2D */ 4120 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4121 cMax = PetscMin(cEnd, cMax); 4122 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4123 fMax = PetscMin(fEnd, fMax); 4124 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 4125 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 */ 4126 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 4127 break; 4128 case 2: 4129 /* Hex 2D */ 4130 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 4131 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 4132 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 4133 break; 4134 default: 4135 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 4136 } 4137 PetscFunctionReturn(0); 4138 } 4139 4140 #undef __FUNCT__ 4141 #define __FUNCT__ "CellRefinerSetConeSizes" 4142 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 4143 { 4144 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 4145 PetscErrorCode ierr; 4146 4147 PetscFunctionBegin; 4148 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4149 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4150 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4151 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4152 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4153 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4154 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 4155 switch (refiner) { 4156 case 1: 4157 /* Simplicial 2D */ 4158 /* All cells have 3 faces */ 4159 for (c = cStart; c < cEnd; ++c) { 4160 for (r = 0; r < 4; ++r) { 4161 const PetscInt newp = (c - cStart)*4 + r; 4162 4163 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 4164 } 4165 } 4166 /* Split faces have 2 vertices and the same cells as the parent */ 4167 for (f = fStart; f < fEnd; ++f) { 4168 for (r = 0; r < 2; ++r) { 4169 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4170 PetscInt size; 4171 4172 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4173 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4174 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4175 } 4176 } 4177 /* Interior faces have 2 vertices and 2 cells */ 4178 for (c = cStart; c < cEnd; ++c) { 4179 for (r = 0; r < 3; ++r) { 4180 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 4181 4182 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4183 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4184 } 4185 } 4186 /* Old vertices have identical supports */ 4187 for (v = vStart; v < vEnd; ++v) { 4188 const PetscInt newp = vStartNew + (v - vStart); 4189 PetscInt size; 4190 4191 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4192 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4193 } 4194 /* Face vertices have 2 + cells*2 supports */ 4195 for (f = fStart; f < fEnd; ++f) { 4196 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4197 PetscInt size; 4198 4199 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4200 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 4201 } 4202 break; 4203 case 2: 4204 /* Hex 2D */ 4205 /* All cells have 4 faces */ 4206 for (c = cStart; c < cEnd; ++c) { 4207 for (r = 0; r < 4; ++r) { 4208 const PetscInt newp = (c - cStart)*4 + r; 4209 4210 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 4211 } 4212 } 4213 /* Split faces have 2 vertices and the same cells as the parent */ 4214 for (f = fStart; f < fEnd; ++f) { 4215 for (r = 0; r < 2; ++r) { 4216 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4217 PetscInt size; 4218 4219 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4220 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4221 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4222 } 4223 } 4224 /* Interior faces have 2 vertices and 2 cells */ 4225 for (c = cStart; c < cEnd; ++c) { 4226 for (r = 0; r < 4; ++r) { 4227 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4228 4229 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4230 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4231 } 4232 } 4233 /* Old vertices have identical supports */ 4234 for (v = vStart; v < vEnd; ++v) { 4235 const PetscInt newp = vStartNew + (v - vStart); 4236 PetscInt size; 4237 4238 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4239 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4240 } 4241 /* Face vertices have 2 + cells supports */ 4242 for (f = fStart; f < fEnd; ++f) { 4243 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4244 PetscInt size; 4245 4246 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4247 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 4248 } 4249 /* Cell vertices have 4 supports */ 4250 for (c = cStart; c < cEnd; ++c) { 4251 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4252 4253 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 4254 } 4255 break; 4256 case 3: 4257 /* Hybrid 2D */ 4258 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4259 cMax = PetscMin(cEnd, cMax); 4260 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4261 fMax = PetscMin(fEnd, fMax); 4262 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 4263 /* Interior cells have 3 faces */ 4264 for (c = cStart; c < cMax; ++c) { 4265 for (r = 0; r < 4; ++r) { 4266 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 4267 4268 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 4269 } 4270 } 4271 /* Hybrid cells have 4 faces */ 4272 for (c = cMax; c < cEnd; ++c) { 4273 for (r = 0; r < 2; ++r) { 4274 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 4275 4276 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 4277 } 4278 } 4279 /* Interior split faces have 2 vertices and the same cells as the parent */ 4280 for (f = fStart; f < fMax; ++f) { 4281 for (r = 0; r < 2; ++r) { 4282 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4283 PetscInt size; 4284 4285 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4286 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4287 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4288 } 4289 } 4290 /* Interior cell faces have 2 vertices and 2 cells */ 4291 for (c = cStart; c < cMax; ++c) { 4292 for (r = 0; r < 3; ++r) { 4293 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 4294 4295 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4296 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4297 } 4298 } 4299 /* Hybrid faces have 2 vertices and the same cells */ 4300 for (f = fMax; f < fEnd; ++f) { 4301 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 4302 PetscInt size; 4303 4304 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4305 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4306 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4307 } 4308 /* Hybrid cell faces have 2 vertices and 2 cells */ 4309 for (c = cMax; c < cEnd; ++c) { 4310 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4311 4312 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4313 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4314 } 4315 /* Old vertices have identical supports */ 4316 for (v = vStart; v < vEnd; ++v) { 4317 const PetscInt newp = vStartNew + (v - vStart); 4318 PetscInt size; 4319 4320 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4321 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4322 } 4323 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 4324 for (f = fStart; f < fMax; ++f) { 4325 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4326 const PetscInt *support; 4327 PetscInt size, newSize = 2, s; 4328 4329 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4330 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4331 for (s = 0; s < size; ++s) { 4332 if (support[s] >= cMax) newSize += 1; 4333 else newSize += 2; 4334 } 4335 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 4336 } 4337 break; 4338 default: 4339 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 4340 } 4341 PetscFunctionReturn(0); 4342 } 4343 4344 #undef __FUNCT__ 4345 #define __FUNCT__ "CellRefinerSetCones" 4346 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 4347 { 4348 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; 4349 PetscInt maxSupportSize, *supportRef; 4350 PetscErrorCode ierr; 4351 4352 PetscFunctionBegin; 4353 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4354 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4355 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4356 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4357 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4358 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4359 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 4360 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 4361 switch (refiner) { 4362 case 1: 4363 /* Simplicial 2D */ 4364 /* 4365 2 4366 |\ 4367 | \ 4368 | \ 4369 | \ 4370 | C \ 4371 | \ 4372 | \ 4373 2---1---1 4374 |\ D / \ 4375 | 2 0 \ 4376 |A \ / B \ 4377 0---0-------1 4378 */ 4379 /* All cells have 3 faces */ 4380 for (c = cStart; c < cEnd; ++c) { 4381 const PetscInt newp = cStartNew + (c - cStart)*4; 4382 const PetscInt *cone, *ornt; 4383 PetscInt coneNew[3], orntNew[3]; 4384 4385 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4386 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4387 /* A triangle */ 4388 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4389 orntNew[0] = ornt[0]; 4390 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 4391 orntNew[1] = -2; 4392 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4393 orntNew[2] = ornt[2]; 4394 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4395 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4396 #if 1 4397 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); 4398 for (p = 0; p < 3; ++p) { 4399 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); 4400 } 4401 #endif 4402 /* B triangle */ 4403 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4404 orntNew[0] = ornt[0]; 4405 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4406 orntNew[1] = ornt[1]; 4407 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 4408 orntNew[2] = -2; 4409 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4410 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4411 #if 1 4412 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); 4413 for (p = 0; p < 3; ++p) { 4414 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); 4415 } 4416 #endif 4417 /* C triangle */ 4418 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 4419 orntNew[0] = -2; 4420 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4421 orntNew[1] = ornt[1]; 4422 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4423 orntNew[2] = ornt[2]; 4424 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4425 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4426 #if 1 4427 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); 4428 for (p = 0; p < 3; ++p) { 4429 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); 4430 } 4431 #endif 4432 /* D triangle */ 4433 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 4434 orntNew[0] = 0; 4435 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 4436 orntNew[1] = 0; 4437 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 4438 orntNew[2] = 0; 4439 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4440 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4441 #if 1 4442 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); 4443 for (p = 0; p < 3; ++p) { 4444 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); 4445 } 4446 #endif 4447 } 4448 /* Split faces have 2 vertices and the same cells as the parent */ 4449 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4450 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4451 for (f = fStart; f < fEnd; ++f) { 4452 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4453 4454 for (r = 0; r < 2; ++r) { 4455 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4456 const PetscInt *cone, *support; 4457 PetscInt coneNew[2], coneSize, c, supportSize, s; 4458 4459 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4460 coneNew[0] = vStartNew + (cone[0] - vStart); 4461 coneNew[1] = vStartNew + (cone[1] - vStart); 4462 coneNew[(r+1)%2] = newv; 4463 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4464 #if 1 4465 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4466 for (p = 0; p < 2; ++p) { 4467 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); 4468 } 4469 #endif 4470 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4471 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4472 for (s = 0; s < supportSize; ++s) { 4473 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4474 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4475 for (c = 0; c < coneSize; ++c) { 4476 if (cone[c] == f) break; 4477 } 4478 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 4479 } 4480 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4481 #if 1 4482 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4483 for (p = 0; p < supportSize; ++p) { 4484 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); 4485 } 4486 #endif 4487 } 4488 } 4489 /* Interior faces have 2 vertices and 2 cells */ 4490 for (c = cStart; c < cEnd; ++c) { 4491 const PetscInt *cone; 4492 4493 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4494 for (r = 0; r < 3; ++r) { 4495 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 4496 PetscInt coneNew[2]; 4497 PetscInt supportNew[2]; 4498 4499 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4500 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 4501 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4502 #if 1 4503 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4504 for (p = 0; p < 2; ++p) { 4505 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); 4506 } 4507 #endif 4508 supportNew[0] = (c - cStart)*4 + (r+1)%3; 4509 supportNew[1] = (c - cStart)*4 + 3; 4510 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4511 #if 1 4512 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4513 for (p = 0; p < 2; ++p) { 4514 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); 4515 } 4516 #endif 4517 } 4518 } 4519 /* Old vertices have identical supports */ 4520 for (v = vStart; v < vEnd; ++v) { 4521 const PetscInt newp = vStartNew + (v - vStart); 4522 const PetscInt *support, *cone; 4523 PetscInt size, s; 4524 4525 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4526 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 4527 for (s = 0; s < size; ++s) { 4528 PetscInt r = 0; 4529 4530 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4531 if (cone[1] == v) r = 1; 4532 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 4533 } 4534 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4535 #if 1 4536 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4537 for (p = 0; p < size; ++p) { 4538 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); 4539 } 4540 #endif 4541 } 4542 /* Face vertices have 2 + cells*2 supports */ 4543 for (f = fStart; f < fEnd; ++f) { 4544 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4545 const PetscInt *cone, *support; 4546 PetscInt size, s; 4547 4548 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4549 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4550 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 4551 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 4552 for (s = 0; s < size; ++s) { 4553 PetscInt r = 0; 4554 4555 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4556 if (cone[1] == f) r = 1; 4557 else if (cone[2] == f) r = 2; 4558 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 4559 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 4560 } 4561 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4562 #if 1 4563 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4564 for (p = 0; p < 2+size*2; ++p) { 4565 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); 4566 } 4567 #endif 4568 } 4569 ierr = PetscFree(supportRef);CHKERRQ(ierr); 4570 break; 4571 case 2: 4572 /* Hex 2D */ 4573 /* 4574 3---------2---------2 4575 | | | 4576 | D 2 C | 4577 | | | 4578 3----3----0----1----1 4579 | | | 4580 | A 0 B | 4581 | | | 4582 0---------0---------1 4583 */ 4584 /* All cells have 4 faces */ 4585 for (c = cStart; c < cEnd; ++c) { 4586 const PetscInt newp = (c - cStart)*4; 4587 const PetscInt *cone, *ornt; 4588 PetscInt coneNew[4], orntNew[4]; 4589 4590 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4591 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4592 /* A quad */ 4593 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4594 orntNew[0] = ornt[0]; 4595 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 4596 orntNew[1] = 0; 4597 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 4598 orntNew[2] = -2; 4599 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 4600 orntNew[3] = ornt[3]; 4601 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4602 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4603 #if 1 4604 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); 4605 for (p = 0; p < 4; ++p) { 4606 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); 4607 } 4608 #endif 4609 /* B quad */ 4610 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4611 orntNew[0] = ornt[0]; 4612 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4613 orntNew[1] = ornt[1]; 4614 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 4615 orntNew[2] = 0; 4616 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 4617 orntNew[3] = -2; 4618 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4619 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4620 #if 1 4621 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); 4622 for (p = 0; p < 4; ++p) { 4623 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); 4624 } 4625 #endif 4626 /* C quad */ 4627 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 4628 orntNew[0] = -2; 4629 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4630 orntNew[1] = ornt[1]; 4631 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4632 orntNew[2] = ornt[2]; 4633 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 4634 orntNew[3] = 0; 4635 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4636 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4637 #if 1 4638 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); 4639 for (p = 0; p < 4; ++p) { 4640 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); 4641 } 4642 #endif 4643 /* D quad */ 4644 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 4645 orntNew[0] = 0; 4646 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 4647 orntNew[1] = -2; 4648 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4649 orntNew[2] = ornt[2]; 4650 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 4651 orntNew[3] = ornt[3]; 4652 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4653 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4654 #if 1 4655 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); 4656 for (p = 0; p < 4; ++p) { 4657 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); 4658 } 4659 #endif 4660 } 4661 /* Split faces have 2 vertices and the same cells as the parent */ 4662 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4663 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4664 for (f = fStart; f < fEnd; ++f) { 4665 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4666 4667 for (r = 0; r < 2; ++r) { 4668 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4669 const PetscInt *cone, *support; 4670 PetscInt coneNew[2], coneSize, c, supportSize, s; 4671 4672 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4673 coneNew[0] = vStartNew + (cone[0] - vStart); 4674 coneNew[1] = vStartNew + (cone[1] - vStart); 4675 coneNew[(r+1)%2] = newv; 4676 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4677 #if 1 4678 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4679 for (p = 0; p < 2; ++p) { 4680 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); 4681 } 4682 #endif 4683 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4684 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4685 for (s = 0; s < supportSize; ++s) { 4686 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4687 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4688 for (c = 0; c < coneSize; ++c) { 4689 if (cone[c] == f) break; 4690 } 4691 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 4692 } 4693 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4694 #if 1 4695 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4696 for (p = 0; p < supportSize; ++p) { 4697 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); 4698 } 4699 #endif 4700 } 4701 } 4702 /* Interior faces have 2 vertices and 2 cells */ 4703 for (c = cStart; c < cEnd; ++c) { 4704 const PetscInt *cone; 4705 PetscInt coneNew[2], supportNew[2]; 4706 4707 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4708 for (r = 0; r < 4; ++r) { 4709 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4710 4711 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4712 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4713 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4714 #if 1 4715 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4716 for (p = 0; p < 2; ++p) { 4717 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); 4718 } 4719 #endif 4720 supportNew[0] = (c - cStart)*4 + r; 4721 supportNew[1] = (c - cStart)*4 + (r+1)%4; 4722 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4723 #if 1 4724 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4725 for (p = 0; p < 2; ++p) { 4726 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); 4727 } 4728 #endif 4729 } 4730 } 4731 /* Old vertices have identical supports */ 4732 for (v = vStart; v < vEnd; ++v) { 4733 const PetscInt newp = vStartNew + (v - vStart); 4734 const PetscInt *support, *cone; 4735 PetscInt size, s; 4736 4737 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4738 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 4739 for (s = 0; s < size; ++s) { 4740 PetscInt r = 0; 4741 4742 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4743 if (cone[1] == v) r = 1; 4744 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 4745 } 4746 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4747 #if 1 4748 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4749 for (p = 0; p < size; ++p) { 4750 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); 4751 } 4752 #endif 4753 } 4754 /* Face vertices have 2 + cells supports */ 4755 for (f = fStart; f < fEnd; ++f) { 4756 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4757 const PetscInt *cone, *support; 4758 PetscInt size, s; 4759 4760 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4761 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4762 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 4763 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 4764 for (s = 0; s < size; ++s) { 4765 PetscInt r = 0; 4766 4767 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4768 if (cone[1] == f) r = 1; 4769 else if (cone[2] == f) r = 2; 4770 else if (cone[3] == f) r = 3; 4771 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 4772 } 4773 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4774 #if 1 4775 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4776 for (p = 0; p < 2+size; ++p) { 4777 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); 4778 } 4779 #endif 4780 } 4781 /* Cell vertices have 4 supports */ 4782 for (c = cStart; c < cEnd; ++c) { 4783 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4784 PetscInt supportNew[4]; 4785 4786 for (r = 0; r < 4; ++r) { 4787 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4788 } 4789 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4790 } 4791 break; 4792 case 3: 4793 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4794 cMax = PetscMin(cEnd, cMax); 4795 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4796 fMax = PetscMin(fEnd, fMax); 4797 /* Interior cells have 3 faces */ 4798 for (c = cStart; c < cMax; ++c) { 4799 const PetscInt newp = cStartNew + (c - cStart)*4; 4800 const PetscInt *cone, *ornt; 4801 PetscInt coneNew[3], orntNew[3]; 4802 4803 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4804 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4805 /* A triangle */ 4806 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4807 orntNew[0] = ornt[0]; 4808 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 4809 orntNew[1] = -2; 4810 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4811 orntNew[2] = ornt[2]; 4812 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4813 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4814 #if 1 4815 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); 4816 for (p = 0; p < 3; ++p) { 4817 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); 4818 } 4819 #endif 4820 /* B triangle */ 4821 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4822 orntNew[0] = ornt[0]; 4823 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4824 orntNew[1] = ornt[1]; 4825 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 4826 orntNew[2] = -2; 4827 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4828 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4829 #if 1 4830 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); 4831 for (p = 0; p < 3; ++p) { 4832 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); 4833 } 4834 #endif 4835 /* C triangle */ 4836 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 4837 orntNew[0] = -2; 4838 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4839 orntNew[1] = ornt[1]; 4840 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4841 orntNew[2] = ornt[2]; 4842 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4843 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4844 #if 1 4845 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); 4846 for (p = 0; p < 3; ++p) { 4847 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); 4848 } 4849 #endif 4850 /* D triangle */ 4851 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 4852 orntNew[0] = 0; 4853 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 4854 orntNew[1] = 0; 4855 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 4856 orntNew[2] = 0; 4857 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4858 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4859 #if 1 4860 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); 4861 for (p = 0; p < 3; ++p) { 4862 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); 4863 } 4864 #endif 4865 } 4866 /* 4867 2----3----3 4868 | | 4869 | B | 4870 | | 4871 0----4--- 1 4872 | | 4873 | A | 4874 | | 4875 0----2----1 4876 */ 4877 /* Hybrid cells have 4 faces */ 4878 for (c = cMax; c < cEnd; ++c) { 4879 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 4880 const PetscInt *cone, *ornt; 4881 PetscInt coneNew[4], orntNew[4]; 4882 4883 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4884 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4885 /* A quad */ 4886 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4887 orntNew[0] = ornt[0]; 4888 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4889 orntNew[1] = ornt[1]; 4890 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 4891 orntNew[2] = 0; 4892 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4893 orntNew[3] = 0; 4894 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4895 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4896 #if 1 4897 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); 4898 for (p = 0; p < 4; ++p) { 4899 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); 4900 } 4901 #endif 4902 /* B quad */ 4903 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4904 orntNew[0] = ornt[0]; 4905 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4906 orntNew[1] = ornt[1]; 4907 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4908 orntNew[2] = 0; 4909 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 4910 orntNew[3] = 0; 4911 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4912 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4913 #if 1 4914 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); 4915 for (p = 0; p < 4; ++p) { 4916 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); 4917 } 4918 #endif 4919 } 4920 /* Interior split faces have 2 vertices and the same cells as the parent */ 4921 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4922 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4923 for (f = fStart; f < fMax; ++f) { 4924 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4925 4926 for (r = 0; r < 2; ++r) { 4927 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4928 const PetscInt *cone, *support; 4929 PetscInt coneNew[2], coneSize, c, supportSize, s; 4930 4931 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4932 coneNew[0] = vStartNew + (cone[0] - vStart); 4933 coneNew[1] = vStartNew + (cone[1] - vStart); 4934 coneNew[(r+1)%2] = newv; 4935 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4936 #if 1 4937 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4938 for (p = 0; p < 2; ++p) { 4939 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); 4940 } 4941 #endif 4942 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4943 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4944 for (s = 0; s < supportSize; ++s) { 4945 if (support[s] >= cMax) { 4946 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 4947 } else { 4948 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4949 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4950 for (c = 0; c < coneSize; ++c) { 4951 if (cone[c] == f) break; 4952 } 4953 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 4954 } 4955 } 4956 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4957 #if 1 4958 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4959 for (p = 0; p < supportSize; ++p) { 4960 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); 4961 } 4962 #endif 4963 } 4964 } 4965 /* Interior cell faces have 2 vertices and 2 cells */ 4966 for (c = cStart; c < cMax; ++c) { 4967 const PetscInt *cone; 4968 4969 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4970 for (r = 0; r < 3; ++r) { 4971 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 4972 PetscInt coneNew[2]; 4973 PetscInt supportNew[2]; 4974 4975 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4976 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 4977 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4978 #if 1 4979 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4980 for (p = 0; p < 2; ++p) { 4981 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); 4982 } 4983 #endif 4984 supportNew[0] = (c - cStart)*4 + (r+1)%3; 4985 supportNew[1] = (c - cStart)*4 + 3; 4986 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4987 #if 1 4988 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4989 for (p = 0; p < 2; ++p) { 4990 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); 4991 } 4992 #endif 4993 } 4994 } 4995 /* Interior hybrid faces have 2 vertices and the same cells */ 4996 for (f = fMax; f < fEnd; ++f) { 4997 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 4998 const PetscInt *cone; 4999 const PetscInt *support; 5000 PetscInt coneNew[2]; 5001 PetscInt supportNew[2]; 5002 PetscInt size, s, r; 5003 5004 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5005 coneNew[0] = vStartNew + (cone[0] - vStart); 5006 coneNew[1] = vStartNew + (cone[1] - vStart); 5007 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5008 #if 1 5009 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5010 for (p = 0; p < 2; ++p) { 5011 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); 5012 } 5013 #endif 5014 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5015 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5016 for (s = 0; s < size; ++s) { 5017 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5018 for (r = 0; r < 2; ++r) { 5019 if (cone[r+2] == f) break; 5020 } 5021 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 5022 } 5023 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5024 #if 1 5025 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5026 for (p = 0; p < size; ++p) { 5027 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); 5028 } 5029 #endif 5030 } 5031 /* Cell hybrid faces have 2 vertices and 2 cells */ 5032 for (c = cMax; c < cEnd; ++c) { 5033 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5034 const PetscInt *cone; 5035 PetscInt coneNew[2]; 5036 PetscInt supportNew[2]; 5037 5038 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5039 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 5040 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 5041 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5042 #if 1 5043 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5044 for (p = 0; p < 2; ++p) { 5045 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); 5046 } 5047 #endif 5048 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 5049 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 5050 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5051 #if 1 5052 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5053 for (p = 0; p < 2; ++p) { 5054 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); 5055 } 5056 #endif 5057 } 5058 /* Old vertices have identical supports */ 5059 for (v = vStart; v < vEnd; ++v) { 5060 const PetscInt newp = vStartNew + (v - vStart); 5061 const PetscInt *support, *cone; 5062 PetscInt size, s; 5063 5064 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5065 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5066 for (s = 0; s < size; ++s) { 5067 if (support[s] >= fMax) { 5068 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 5069 } else { 5070 PetscInt r = 0; 5071 5072 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5073 if (cone[1] == v) r = 1; 5074 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5075 } 5076 } 5077 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5078 #if 1 5079 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5080 for (p = 0; p < size; ++p) { 5081 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); 5082 } 5083 #endif 5084 } 5085 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5086 for (f = fStart; f < fMax; ++f) { 5087 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5088 const PetscInt *cone, *support; 5089 PetscInt size, newSize = 2, s; 5090 5091 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5092 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5093 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5094 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5095 for (s = 0; s < size; ++s) { 5096 PetscInt r = 0; 5097 5098 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5099 if (support[s] >= cMax) { 5100 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 5101 5102 newSize += 1; 5103 } else { 5104 if (cone[1] == f) r = 1; 5105 else if (cone[2] == f) r = 2; 5106 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5107 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 5108 5109 newSize += 2; 5110 } 5111 } 5112 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5113 #if 1 5114 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5115 for (p = 0; p < newSize; ++p) { 5116 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); 5117 } 5118 #endif 5119 } 5120 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5121 break; 5122 default: 5123 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5124 } 5125 PetscFunctionReturn(0); 5126 } 5127 5128 #undef __FUNCT__ 5129 #define __FUNCT__ "CellRefinerSetCoordinates" 5130 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5131 { 5132 PetscSection coordSection, coordSectionNew; 5133 Vec coordinates, coordinatesNew; 5134 PetscScalar *coords, *coordsNew; 5135 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 5136 PetscErrorCode ierr; 5137 5138 PetscFunctionBegin; 5139 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5140 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5141 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5142 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5143 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5144 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 5145 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 5146 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5147 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 5148 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 5149 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 5150 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 5151 if (fMax < 0) fMax = fEnd; 5152 switch (refiner) { 5153 case 1: 5154 case 2: 5155 case 3: 5156 /* Simplicial and Hex 2D */ 5157 /* All vertices have the dim coordinates */ 5158 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 5159 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 5160 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 5161 } 5162 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 5163 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 5164 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5165 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 5166 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 5167 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 5168 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 5169 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 5170 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 5171 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5172 /* Old vertices have the same coordinates */ 5173 for (v = vStart; v < vEnd; ++v) { 5174 const PetscInt newv = vStartNew + (v - vStart); 5175 PetscInt off, offnew, d; 5176 5177 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5178 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5179 for (d = 0; d < dim; ++d) { 5180 coordsNew[offnew+d] = coords[off+d]; 5181 } 5182 } 5183 /* Face vertices have the average of endpoint coordinates */ 5184 for (f = fStart; f < fMax; ++f) { 5185 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5186 const PetscInt *cone; 5187 PetscInt coneSize, offA, offB, offnew, d; 5188 5189 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 5190 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 5191 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5192 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5193 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5194 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5195 for (d = 0; d < dim; ++d) { 5196 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 5197 } 5198 } 5199 /* Just Hex 2D */ 5200 if (refiner == 2) { 5201 /* Cell vertices have the average of corner coordinates */ 5202 for (c = cStart; c < cEnd; ++c) { 5203 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5204 PetscInt *cone = NULL; 5205 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 5206 5207 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5208 for (p = 0; p < closureSize*2; p += 2) { 5209 const PetscInt point = cone[p]; 5210 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 5211 } 5212 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 5213 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5214 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5215 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 5216 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 5217 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5218 for (d = 0; d < dim; ++d) { 5219 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 5220 } 5221 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5222 } 5223 } 5224 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 5225 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5226 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 5227 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 5228 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 5229 break; 5230 default: 5231 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5232 } 5233 PetscFunctionReturn(0); 5234 } 5235 5236 #undef __FUNCT__ 5237 #define __FUNCT__ "DMPlexCreateProcessSF" 5238 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 5239 { 5240 PetscInt numRoots, numLeaves, l; 5241 const PetscInt *localPoints; 5242 const PetscSFNode *remotePoints; 5243 PetscInt *localPointsNew; 5244 PetscSFNode *remotePointsNew; 5245 PetscInt *ranks, *ranksNew; 5246 PetscErrorCode ierr; 5247 5248 PetscFunctionBegin; 5249 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5250 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 5251 for (l = 0; l < numLeaves; ++l) { 5252 ranks[l] = remotePoints[l].rank; 5253 } 5254 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 5255 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 5256 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 5257 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 5258 for (l = 0; l < numLeaves; ++l) { 5259 ranksNew[l] = ranks[l]; 5260 localPointsNew[l] = l; 5261 remotePointsNew[l].index = 0; 5262 remotePointsNew[l].rank = ranksNew[l]; 5263 } 5264 ierr = PetscFree(ranks);CHKERRQ(ierr); 5265 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 5266 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 5267 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 5268 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 5269 PetscFunctionReturn(0); 5270 } 5271 5272 #undef __FUNCT__ 5273 #define __FUNCT__ "CellRefinerCreateSF" 5274 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5275 { 5276 PetscSF sf, sfNew, sfProcess; 5277 IS processRanks; 5278 MPI_Datatype depthType; 5279 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 5280 const PetscInt *localPoints, *neighbors; 5281 const PetscSFNode *remotePoints; 5282 PetscInt *localPointsNew; 5283 PetscSFNode *remotePointsNew; 5284 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 5285 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 5286 PetscErrorCode ierr; 5287 5288 PetscFunctionBegin; 5289 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 5290 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5291 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5292 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5293 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5294 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5295 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5296 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5297 switch (refiner) { 5298 case 3: 5299 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5300 cMax = PetscMin(cEnd, cMax); 5301 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5302 fMax = PetscMin(fEnd, fMax); 5303 } 5304 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 5305 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 5306 /* Caculate size of new SF */ 5307 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5308 if (numRoots < 0) PetscFunctionReturn(0); 5309 for (l = 0; l < numLeaves; ++l) { 5310 const PetscInt p = localPoints[l]; 5311 5312 switch (refiner) { 5313 case 1: 5314 /* Simplicial 2D */ 5315 if ((p >= vStart) && (p < vEnd)) { 5316 /* Old vertices stay the same */ 5317 ++numLeavesNew; 5318 } else if ((p >= fStart) && (p < fEnd)) { 5319 /* Old faces add new faces and vertex */ 5320 numLeavesNew += 1 + 2; 5321 } else if ((p >= cStart) && (p < cEnd)) { 5322 /* Old cells add new cells and interior faces */ 5323 numLeavesNew += 4 + 3; 5324 } 5325 break; 5326 case 2: 5327 /* Hex 2D */ 5328 if ((p >= vStart) && (p < vEnd)) { 5329 /* Old vertices stay the same */ 5330 ++numLeavesNew; 5331 } else if ((p >= fStart) && (p < fEnd)) { 5332 /* Old faces add new faces and vertex */ 5333 numLeavesNew += 1 + 2; 5334 } else if ((p >= cStart) && (p < cEnd)) { 5335 /* Old cells add new cells and interior faces */ 5336 numLeavesNew += 4 + 4; 5337 } 5338 break; 5339 default: 5340 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5341 } 5342 } 5343 /* Communicate depthSizes for each remote rank */ 5344 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 5345 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 5346 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 5347 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); 5348 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 5349 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 5350 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 5351 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 5352 for (n = 0; n < numNeighbors; ++n) { 5353 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 5354 } 5355 depthSizeOld[depth] = cMax; 5356 depthSizeOld[0] = vMax; 5357 depthSizeOld[depth-1] = fMax; 5358 depthSizeOld[1] = eMax; 5359 5360 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 5361 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 5362 5363 depthSizeOld[depth] = cEnd - cStart; 5364 depthSizeOld[0] = vEnd - vStart; 5365 depthSizeOld[depth-1] = fEnd - fStart; 5366 depthSizeOld[1] = eEnd - eStart; 5367 5368 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 5369 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 5370 for (n = 0; n < numNeighbors; ++n) { 5371 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 5372 } 5373 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 5374 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 5375 /* Calculate new point SF */ 5376 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 5377 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 5378 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 5379 for (l = 0, m = 0; l < numLeaves; ++l) { 5380 PetscInt p = localPoints[l]; 5381 PetscInt rp = remotePoints[l].index, n; 5382 PetscMPIInt rrank = remotePoints[l].rank; 5383 5384 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 5385 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 5386 switch (refiner) { 5387 case 1: 5388 /* Simplicial 2D */ 5389 if ((p >= vStart) && (p < vEnd)) { 5390 /* Old vertices stay the same */ 5391 localPointsNew[m] = vStartNew + (p - vStart); 5392 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5393 remotePointsNew[m].rank = rrank; 5394 ++m; 5395 } else if ((p >= fStart) && (p < fEnd)) { 5396 /* Old faces add new faces and vertex */ 5397 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5398 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5399 remotePointsNew[m].rank = rrank; 5400 ++m; 5401 for (r = 0; r < 2; ++r, ++m) { 5402 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5403 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5404 remotePointsNew[m].rank = rrank; 5405 } 5406 } else if ((p >= cStart) && (p < cEnd)) { 5407 /* Old cells add new cells and interior faces */ 5408 for (r = 0; r < 4; ++r, ++m) { 5409 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5410 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5411 remotePointsNew[m].rank = rrank; 5412 } 5413 for (r = 0; r < 3; ++r, ++m) { 5414 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5415 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 5416 remotePointsNew[m].rank = rrank; 5417 } 5418 } 5419 break; 5420 case 2: 5421 /* Hex 2D */ 5422 if ((p >= vStart) && (p < vEnd)) { 5423 /* Old vertices stay the same */ 5424 localPointsNew[m] = vStartNew + (p - vStart); 5425 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5426 remotePointsNew[m].rank = rrank; 5427 ++m; 5428 } else if ((p >= fStart) && (p < fEnd)) { 5429 /* Old faces add new faces and vertex */ 5430 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5431 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5432 remotePointsNew[m].rank = rrank; 5433 ++m; 5434 for (r = 0; r < 2; ++r, ++m) { 5435 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5436 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5437 remotePointsNew[m].rank = rrank; 5438 } 5439 } else if ((p >= cStart) && (p < cEnd)) { 5440 /* Old cells add new cells and interior faces */ 5441 for (r = 0; r < 4; ++r, ++m) { 5442 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5443 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5444 remotePointsNew[m].rank = rrank; 5445 } 5446 for (r = 0; r < 4; ++r, ++m) { 5447 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 5448 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 5449 remotePointsNew[m].rank = rrank; 5450 } 5451 } 5452 break; 5453 case 3: 5454 /* Hybrid simplicial 2D */ 5455 if ((p >= vStart) && (p < vEnd)) { 5456 /* Old vertices stay the same */ 5457 localPointsNew[m] = vStartNew + (p - vStart); 5458 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5459 remotePointsNew[m].rank = rrank; 5460 ++m; 5461 } else if ((p >= fStart) && (p < fMax)) { 5462 /* Old interior faces add new faces and vertex */ 5463 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5464 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5465 remotePointsNew[m].rank = rrank; 5466 ++m; 5467 for (r = 0; r < 2; ++r, ++m) { 5468 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5469 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5470 remotePointsNew[m].rank = rrank; 5471 } 5472 } else if ((p >= fMax) && (p < fEnd)) { 5473 /* Old hybrid faces stay the same */ 5474 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 5475 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 5476 remotePointsNew[m].rank = rrank; 5477 ++m; 5478 } else if ((p >= cStart) && (p < cMax)) { 5479 /* Old interior cells add new cells and interior faces */ 5480 for (r = 0; r < 4; ++r, ++m) { 5481 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5482 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5483 remotePointsNew[m].rank = rrank; 5484 } 5485 for (r = 0; r < 3; ++r, ++m) { 5486 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 5487 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 5488 remotePointsNew[m].rank = rrank; 5489 } 5490 } else if ((p >= cStart) && (p < cMax)) { 5491 /* Old hybrid cells add new cells and hybrid face */ 5492 for (r = 0; r < 2; ++r, ++m) { 5493 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5494 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5495 remotePointsNew[m].rank = rrank; 5496 } 5497 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 5498 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]); 5499 remotePointsNew[m].rank = rrank; 5500 ++m; 5501 } 5502 break; 5503 default: 5504 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5505 } 5506 } 5507 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 5508 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 5509 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 5510 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 5511 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 5512 PetscFunctionReturn(0); 5513 } 5514 5515 #undef __FUNCT__ 5516 #define __FUNCT__ "CellRefinerCreateLabels" 5517 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5518 { 5519 PetscInt numLabels, l; 5520 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 5521 PetscErrorCode ierr; 5522 5523 PetscFunctionBegin; 5524 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5525 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5526 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5527 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5528 5529 cStartNew = 0; 5530 vStartNew = depthSize[2]; 5531 fStartNew = depthSize[2] + depthSize[0]; 5532 5533 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 5534 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5535 switch (refiner) { 5536 case 3: 5537 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5538 cMax = PetscMin(cEnd, cMax); 5539 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5540 fMax = PetscMin(fEnd, fMax); 5541 } 5542 for (l = 0; l < numLabels; ++l) { 5543 DMLabel label, labelNew; 5544 const char *lname; 5545 PetscBool isDepth; 5546 IS valueIS; 5547 const PetscInt *values; 5548 PetscInt numValues, val; 5549 5550 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 5551 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 5552 if (isDepth) continue; 5553 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 5554 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 5555 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 5556 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 5557 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 5558 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 5559 for (val = 0; val < numValues; ++val) { 5560 IS pointIS; 5561 const PetscInt *points; 5562 PetscInt numPoints, n; 5563 5564 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 5565 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 5566 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 5567 for (n = 0; n < numPoints; ++n) { 5568 const PetscInt p = points[n]; 5569 switch (refiner) { 5570 case 1: 5571 /* Simplicial 2D */ 5572 if ((p >= vStart) && (p < vEnd)) { 5573 /* Old vertices stay the same */ 5574 newp = vStartNew + (p - vStart); 5575 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5576 } else if ((p >= fStart) && (p < fEnd)) { 5577 /* Old faces add new faces and vertex */ 5578 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5579 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5580 for (r = 0; r < 2; ++r) { 5581 newp = fStartNew + (p - fStart)*2 + r; 5582 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5583 } 5584 } else if ((p >= cStart) && (p < cEnd)) { 5585 /* Old cells add new cells and interior faces */ 5586 for (r = 0; r < 4; ++r) { 5587 newp = cStartNew + (p - cStart)*4 + r; 5588 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5589 } 5590 for (r = 0; r < 3; ++r) { 5591 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5592 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5593 } 5594 } 5595 break; 5596 case 2: 5597 /* Hex 2D */ 5598 if ((p >= vStart) && (p < vEnd)) { 5599 /* Old vertices stay the same */ 5600 newp = vStartNew + (p - vStart); 5601 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5602 } else if ((p >= fStart) && (p < fEnd)) { 5603 /* Old faces add new faces and vertex */ 5604 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5605 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5606 for (r = 0; r < 2; ++r) { 5607 newp = fStartNew + (p - fStart)*2 + r; 5608 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5609 } 5610 } else if ((p >= cStart) && (p < cEnd)) { 5611 /* Old cells add new cells and interior faces and vertex */ 5612 for (r = 0; r < 4; ++r) { 5613 newp = cStartNew + (p - cStart)*4 + r; 5614 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5615 } 5616 for (r = 0; r < 4; ++r) { 5617 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 5618 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5619 } 5620 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 5621 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5622 } 5623 break; 5624 case 3: 5625 /* Hybrid simplicial 2D */ 5626 if ((p >= vStart) && (p < vEnd)) { 5627 /* Old vertices stay the same */ 5628 newp = vStartNew + (p - vStart); 5629 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5630 } else if ((p >= fStart) && (p < fMax)) { 5631 /* Old interior faces add new faces and vertex */ 5632 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5633 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5634 for (r = 0; r < 2; ++r) { 5635 newp = fStartNew + (p - fStart)*2 + r; 5636 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5637 } 5638 } else if ((p >= fMax) && (p < fEnd)) { 5639 /* Old hybrid faces stay the same */ 5640 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 5641 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5642 } else if ((p >= cStart) && (p < cMax)) { 5643 /* Old interior cells add new cells and interior faces */ 5644 for (r = 0; r < 4; ++r) { 5645 newp = cStartNew + (p - cStart)*4 + r; 5646 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5647 } 5648 for (r = 0; r < 3; ++r) { 5649 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5650 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5651 } 5652 } else if ((p >= cMax) && (p < cEnd)) { 5653 /* Old hybrid cells add new cells and hybrid face */ 5654 for (r = 0; r < 2; ++r) { 5655 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 5656 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5657 } 5658 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 5659 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5660 } 5661 break; 5662 default: 5663 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5664 } 5665 } 5666 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 5667 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 5668 } 5669 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 5670 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 5671 if (0) { 5672 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 5673 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 5674 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 5675 } 5676 } 5677 PetscFunctionReturn(0); 5678 } 5679 5680 #undef __FUNCT__ 5681 #define __FUNCT__ "DMPlexRefine_Uniform" 5682 /* This will only work for interpolated meshes */ 5683 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 5684 { 5685 DM rdm; 5686 PetscInt *depthSize; 5687 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 5688 PetscErrorCode ierr; 5689 5690 PetscFunctionBegin; 5691 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 5692 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 5693 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5694 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 5695 /* Calculate number of new points of each depth */ 5696 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5697 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 5698 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 5699 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 5700 /* Step 1: Set chart */ 5701 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 5702 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 5703 /* Step 2: Set cone/support sizes */ 5704 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5705 /* Step 3: Setup refined DM */ 5706 ierr = DMSetUp(rdm);CHKERRQ(ierr); 5707 /* Step 4: Set cones and supports */ 5708 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5709 /* Step 5: Stratify */ 5710 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 5711 /* Step 6: Set coordinates for vertices */ 5712 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5713 /* Step 7: Create pointSF */ 5714 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5715 /* Step 8: Create labels */ 5716 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5717 ierr = PetscFree(depthSize);CHKERRQ(ierr); 5718 5719 *dmRefined = rdm; 5720 PetscFunctionReturn(0); 5721 } 5722 5723 #undef __FUNCT__ 5724 #define __FUNCT__ "DMPlexSetRefinementUniform" 5725 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 5726 { 5727 DM_Plex *mesh = (DM_Plex*) dm->data; 5728 5729 PetscFunctionBegin; 5730 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5731 mesh->refinementUniform = refinementUniform; 5732 PetscFunctionReturn(0); 5733 } 5734 5735 #undef __FUNCT__ 5736 #define __FUNCT__ "DMPlexGetRefinementUniform" 5737 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 5738 { 5739 DM_Plex *mesh = (DM_Plex*) dm->data; 5740 5741 PetscFunctionBegin; 5742 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5743 PetscValidPointer(refinementUniform, 2); 5744 *refinementUniform = mesh->refinementUniform; 5745 PetscFunctionReturn(0); 5746 } 5747 5748 #undef __FUNCT__ 5749 #define __FUNCT__ "DMPlexSetRefinementLimit" 5750 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 5751 { 5752 DM_Plex *mesh = (DM_Plex*) dm->data; 5753 5754 PetscFunctionBegin; 5755 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5756 mesh->refinementLimit = refinementLimit; 5757 PetscFunctionReturn(0); 5758 } 5759 5760 #undef __FUNCT__ 5761 #define __FUNCT__ "DMPlexGetRefinementLimit" 5762 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 5763 { 5764 DM_Plex *mesh = (DM_Plex*) dm->data; 5765 5766 PetscFunctionBegin; 5767 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5768 PetscValidPointer(refinementLimit, 2); 5769 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 5770 *refinementLimit = mesh->refinementLimit; 5771 PetscFunctionReturn(0); 5772 } 5773 5774 #undef __FUNCT__ 5775 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 5776 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 5777 { 5778 PetscInt dim, cStart, coneSize, cMax; 5779 PetscErrorCode ierr; 5780 5781 PetscFunctionBegin; 5782 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5783 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 5784 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 5785 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5786 switch (dim) { 5787 case 2: 5788 switch (coneSize) { 5789 case 3: 5790 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 5791 else *cellRefiner = 1; /* Triangular */ 5792 break; 5793 case 4: 5794 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 5795 else *cellRefiner = 2; /* Quadrilateral */ 5796 break; 5797 default: 5798 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 5799 } 5800 break; 5801 default: 5802 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 5803 } 5804 PetscFunctionReturn(0); 5805 } 5806 5807 #undef __FUNCT__ 5808 #define __FUNCT__ "DMRefine_Plex" 5809 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 5810 { 5811 PetscReal refinementLimit; 5812 PetscInt dim, cStart, cEnd; 5813 char genname[1024], *name = NULL; 5814 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5815 PetscErrorCode ierr; 5816 5817 PetscFunctionBegin; 5818 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 5819 if (isUniform) { 5820 CellRefiner cellRefiner; 5821 5822 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 5823 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 5824 PetscFunctionReturn(0); 5825 } 5826 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 5827 if (refinementLimit == 0.0) PetscFunctionReturn(0); 5828 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5829 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5830 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5831 if (flg) name = genname; 5832 if (name) { 5833 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5834 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5835 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5836 } 5837 switch (dim) { 5838 case 2: 5839 if (!name || isTriangle) { 5840 #if defined(PETSC_HAVE_TRIANGLE) 5841 double *maxVolumes; 5842 PetscInt c; 5843 5844 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 5845 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5846 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5847 ierr = PetscFree(maxVolumes);CHKERRQ(ierr); 5848 #else 5849 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 5850 #endif 5851 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5852 break; 5853 case 3: 5854 if (!name || isCTetgen) { 5855 #if defined(PETSC_HAVE_CTETGEN) 5856 PetscReal *maxVolumes; 5857 PetscInt c; 5858 5859 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 5860 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5861 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5862 #else 5863 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5864 #endif 5865 } else if (isTetgen) { 5866 #if defined(PETSC_HAVE_TETGEN) 5867 double *maxVolumes; 5868 PetscInt c; 5869 5870 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 5871 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5872 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5873 #else 5874 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5875 #endif 5876 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5877 break; 5878 default: 5879 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 5880 } 5881 PetscFunctionReturn(0); 5882 } 5883 5884 #undef __FUNCT__ 5885 #define __FUNCT__ "DMPlexGetDepth" 5886 /*@ 5887 DMPlexGetDepth - get the number of strata 5888 5889 Not Collective 5890 5891 Input Parameters: 5892 . dm - The DMPlex object 5893 5894 Output Parameters: 5895 . depth - number of strata 5896 5897 Level: developer 5898 5899 Notes: 5900 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 5901 5902 .keywords: mesh, points 5903 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 5904 @*/ 5905 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5906 { 5907 PetscInt d; 5908 PetscErrorCode ierr; 5909 5910 PetscFunctionBegin; 5911 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5912 PetscValidPointer(depth, 2); 5913 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 5914 *depth = d-1; 5915 PetscFunctionReturn(0); 5916 } 5917 5918 #undef __FUNCT__ 5919 #define __FUNCT__ "DMPlexGetDepthStratum" 5920 /*@ 5921 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 5922 5923 Not Collective 5924 5925 Input Parameters: 5926 + dm - The DMPlex object 5927 - stratumValue - The requested depth 5928 5929 Output Parameters: 5930 + start - The first point at this depth 5931 - end - One beyond the last point at this depth 5932 5933 Level: developer 5934 5935 .keywords: mesh, points 5936 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 5937 @*/ 5938 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 5939 { 5940 DM_Plex *mesh = (DM_Plex*) dm->data; 5941 DMLabel next = mesh->labels; 5942 PetscBool flg = PETSC_FALSE; 5943 PetscInt depth; 5944 PetscErrorCode ierr; 5945 5946 PetscFunctionBegin; 5947 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5948 if (stratumValue < 0) { 5949 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 5950 PetscFunctionReturn(0); 5951 } else { 5952 PetscInt pStart, pEnd; 5953 5954 if (start) *start = 0; 5955 if (end) *end = 0; 5956 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5957 if (pStart == pEnd) PetscFunctionReturn(0); 5958 } 5959 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 5960 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 5961 /* We should have a generic GetLabel() and a Label class */ 5962 while (next) { 5963 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 5964 if (flg) break; 5965 next = next->next; 5966 } 5967 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 5968 depth = stratumValue; 5969 if ((depth < 0) || (depth >= next->numStrata)) { 5970 if (start) *start = 0; 5971 if (end) *end = 0; 5972 } else { 5973 if (start) *start = next->points[next->stratumOffsets[depth]]; 5974 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 5975 } 5976 PetscFunctionReturn(0); 5977 } 5978 5979 #undef __FUNCT__ 5980 #define __FUNCT__ "DMPlexGetHeightStratum" 5981 /*@ 5982 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 5983 5984 Not Collective 5985 5986 Input Parameters: 5987 + dm - The DMPlex object 5988 - stratumValue - The requested height 5989 5990 Output Parameters: 5991 + start - The first point at this height 5992 - end - One beyond the last point at this height 5993 5994 Level: developer 5995 5996 .keywords: mesh, points 5997 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 5998 @*/ 5999 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 6000 { 6001 DM_Plex *mesh = (DM_Plex*) dm->data; 6002 DMLabel next = mesh->labels; 6003 PetscBool flg = PETSC_FALSE; 6004 PetscInt depth; 6005 PetscErrorCode ierr; 6006 6007 PetscFunctionBegin; 6008 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6009 if (stratumValue < 0) { 6010 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 6011 } else { 6012 PetscInt pStart, pEnd; 6013 6014 if (start) *start = 0; 6015 if (end) *end = 0; 6016 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6017 if (pStart == pEnd) PetscFunctionReturn(0); 6018 } 6019 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6020 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6021 /* We should have a generic GetLabel() and a Label class */ 6022 while (next) { 6023 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6024 if (flg) break; 6025 next = next->next; 6026 } 6027 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6028 depth = next->stratumValues[next->numStrata-1] - stratumValue; 6029 if ((depth < 0) || (depth >= next->numStrata)) { 6030 if (start) *start = 0; 6031 if (end) *end = 0; 6032 } else { 6033 if (start) *start = next->points[next->stratumOffsets[depth]]; 6034 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 6035 } 6036 PetscFunctionReturn(0); 6037 } 6038 6039 #undef __FUNCT__ 6040 #define __FUNCT__ "DMPlexCreateSectionInitial" 6041 /* Set the number of dof on each point and separate by fields */ 6042 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 6043 { 6044 PetscInt *numDofTot; 6045 PetscInt pStart = 0, pEnd = 0; 6046 PetscInt p, d, f; 6047 PetscErrorCode ierr; 6048 6049 PetscFunctionBegin; 6050 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 6051 for (d = 0; d <= dim; ++d) { 6052 numDofTot[d] = 0; 6053 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 6054 } 6055 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 6056 if (numFields > 0) { 6057 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 6058 if (numComp) { 6059 for (f = 0; f < numFields; ++f) { 6060 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 6061 } 6062 } 6063 } 6064 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6065 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 6066 for (d = 0; d <= dim; ++d) { 6067 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 6068 for (p = pStart; p < pEnd; ++p) { 6069 for (f = 0; f < numFields; ++f) { 6070 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 6071 } 6072 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 6073 } 6074 } 6075 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 6076 PetscFunctionReturn(0); 6077 } 6078 6079 #undef __FUNCT__ 6080 #define __FUNCT__ "DMPlexCreateSectionBCDof" 6081 /* Set the number of dof on each point and separate by fields 6082 If constDof is PETSC_DETERMINE, constrain every dof on the point 6083 */ 6084 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 6085 { 6086 PetscInt numFields; 6087 PetscInt bc; 6088 PetscErrorCode ierr; 6089 6090 PetscFunctionBegin; 6091 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6092 for (bc = 0; bc < numBC; ++bc) { 6093 PetscInt field = 0; 6094 const PetscInt *idx; 6095 PetscInt n, i; 6096 6097 if (numFields) field = bcField[bc]; 6098 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 6099 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6100 for (i = 0; i < n; ++i) { 6101 const PetscInt p = idx[i]; 6102 PetscInt numConst = constDof; 6103 6104 /* Constrain every dof on the point */ 6105 if (numConst < 0) { 6106 if (numFields) { 6107 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 6108 } else { 6109 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 6110 } 6111 } 6112 if (numFields) { 6113 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 6114 } 6115 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 6116 } 6117 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6118 } 6119 PetscFunctionReturn(0); 6120 } 6121 6122 #undef __FUNCT__ 6123 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 6124 /* Set the constrained indices on each point and separate by fields */ 6125 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 6126 { 6127 PetscInt *maxConstraints; 6128 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 6129 PetscErrorCode ierr; 6130 6131 PetscFunctionBegin; 6132 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6133 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6134 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 6135 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 6136 for (p = pStart; p < pEnd; ++p) { 6137 PetscInt cdof; 6138 6139 if (numFields) { 6140 for (f = 0; f < numFields; ++f) { 6141 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 6142 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 6143 } 6144 } else { 6145 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6146 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 6147 } 6148 } 6149 for (f = 0; f < numFields; ++f) { 6150 maxConstraints[numFields] += maxConstraints[f]; 6151 } 6152 if (maxConstraints[numFields]) { 6153 PetscInt *indices; 6154 6155 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 6156 for (p = pStart; p < pEnd; ++p) { 6157 PetscInt cdof, d; 6158 6159 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6160 if (cdof) { 6161 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 6162 if (numFields) { 6163 PetscInt numConst = 0, foff = 0; 6164 6165 for (f = 0; f < numFields; ++f) { 6166 PetscInt cfdof, fdof; 6167 6168 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 6169 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 6170 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 6171 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 6172 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 6173 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 6174 numConst += cfdof; 6175 foff += fdof; 6176 } 6177 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 6178 } else { 6179 for (d = 0; d < cdof; ++d) indices[d] = d; 6180 } 6181 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 6182 } 6183 } 6184 ierr = PetscFree(indices);CHKERRQ(ierr); 6185 } 6186 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 6187 PetscFunctionReturn(0); 6188 } 6189 6190 #undef __FUNCT__ 6191 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 6192 /* Set the constrained field indices on each point */ 6193 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 6194 { 6195 const PetscInt *points, *indices; 6196 PetscInt numFields, maxDof, numPoints, p, numConstraints; 6197 PetscErrorCode ierr; 6198 6199 PetscFunctionBegin; 6200 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6201 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 6202 6203 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 6204 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 6205 if (!constraintIndices) { 6206 PetscInt *idx, i; 6207 6208 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6209 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 6210 for (i = 0; i < maxDof; ++i) idx[i] = i; 6211 for (p = 0; p < numPoints; ++p) { 6212 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 6213 } 6214 ierr = PetscFree(idx);CHKERRQ(ierr); 6215 } else { 6216 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 6217 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 6218 for (p = 0; p < numPoints; ++p) { 6219 PetscInt fcdof; 6220 6221 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 6222 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); 6223 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 6224 } 6225 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 6226 } 6227 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 6228 PetscFunctionReturn(0); 6229 } 6230 6231 #undef __FUNCT__ 6232 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 6233 /* Set the constrained indices on each point and separate by fields */ 6234 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 6235 { 6236 PetscInt *indices; 6237 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 6238 PetscErrorCode ierr; 6239 6240 PetscFunctionBegin; 6241 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6242 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 6243 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6244 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 6245 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6246 for (p = pStart; p < pEnd; ++p) { 6247 PetscInt cdof, d; 6248 6249 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6250 if (cdof) { 6251 PetscInt numConst = 0, foff = 0; 6252 6253 for (f = 0; f < numFields; ++f) { 6254 const PetscInt *fcind; 6255 PetscInt fdof, fcdof; 6256 6257 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 6258 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 6259 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 6260 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 6261 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 6262 foff += fdof; 6263 numConst += fcdof; 6264 } 6265 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 6266 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 6267 } 6268 } 6269 ierr = PetscFree(indices);CHKERRQ(ierr); 6270 PetscFunctionReturn(0); 6271 } 6272 6273 #undef __FUNCT__ 6274 #define __FUNCT__ "DMPlexCreateSection" 6275 /*@C 6276 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 6277 6278 Not Collective 6279 6280 Input Parameters: 6281 + dm - The DMPlex object 6282 . dim - The spatial dimension of the problem 6283 . numFields - The number of fields in the problem 6284 . numComp - An array of size numFields that holds the number of components for each field 6285 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 6286 . numBC - The number of boundary conditions 6287 . bcField - An array of size numBC giving the field number for each boundry condition 6288 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 6289 6290 Output Parameter: 6291 . section - The PetscSection object 6292 6293 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 6294 nubmer of dof for field 0 on each edge. 6295 6296 Level: developer 6297 6298 Fortran Notes: 6299 A Fortran 90 version is available as DMPlexCreateSectionF90() 6300 6301 .keywords: mesh, elements 6302 .seealso: DMPlexCreate(), PetscSectionCreate() 6303 @*/ 6304 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 6305 { 6306 PetscErrorCode ierr; 6307 6308 PetscFunctionBegin; 6309 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 6310 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 6311 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 6312 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 6313 { 6314 PetscBool view = PETSC_FALSE; 6315 6316 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 6317 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 6318 } 6319 PetscFunctionReturn(0); 6320 } 6321 6322 #undef __FUNCT__ 6323 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 6324 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 6325 { 6326 PetscSection section; 6327 PetscErrorCode ierr; 6328 6329 PetscFunctionBegin; 6330 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 6331 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6332 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 6333 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6334 PetscFunctionReturn(0); 6335 } 6336 6337 #undef __FUNCT__ 6338 #define __FUNCT__ "DMPlexGetCoordinateSection" 6339 /*@ 6340 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6341 6342 Not Collective 6343 6344 Input Parameter: 6345 . dm - The DMPlex object 6346 6347 Output Parameter: 6348 . section - The PetscSection object 6349 6350 Level: intermediate 6351 6352 .keywords: mesh, coordinates 6353 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6354 @*/ 6355 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 6356 { 6357 DM cdm; 6358 PetscErrorCode ierr; 6359 6360 PetscFunctionBegin; 6361 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6362 PetscValidPointer(section, 2); 6363 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6364 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 6365 PetscFunctionReturn(0); 6366 } 6367 6368 #undef __FUNCT__ 6369 #define __FUNCT__ "DMPlexSetCoordinateSection" 6370 /*@ 6371 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 6372 6373 Not Collective 6374 6375 Input Parameters: 6376 + dm - The DMPlex object 6377 - section - The PetscSection object 6378 6379 Level: intermediate 6380 6381 .keywords: mesh, coordinates 6382 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6383 @*/ 6384 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 6385 { 6386 DM cdm; 6387 PetscErrorCode ierr; 6388 6389 PetscFunctionBegin; 6390 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6391 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 6392 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6393 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 6394 PetscFunctionReturn(0); 6395 } 6396 6397 #undef __FUNCT__ 6398 #define __FUNCT__ "DMPlexGetConeSection" 6399 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 6400 { 6401 DM_Plex *mesh = (DM_Plex*) dm->data; 6402 6403 PetscFunctionBegin; 6404 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6405 if (section) *section = mesh->coneSection; 6406 PetscFunctionReturn(0); 6407 } 6408 6409 #undef __FUNCT__ 6410 #define __FUNCT__ "DMPlexGetCones" 6411 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 6412 { 6413 DM_Plex *mesh = (DM_Plex*) dm->data; 6414 6415 PetscFunctionBegin; 6416 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6417 if (cones) *cones = mesh->cones; 6418 PetscFunctionReturn(0); 6419 } 6420 6421 #undef __FUNCT__ 6422 #define __FUNCT__ "DMPlexGetConeOrientations" 6423 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 6424 { 6425 DM_Plex *mesh = (DM_Plex*) dm->data; 6426 6427 PetscFunctionBegin; 6428 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6429 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 6430 PetscFunctionReturn(0); 6431 } 6432 6433 /******************************** FEM Support **********************************/ 6434 6435 #undef __FUNCT__ 6436 #define __FUNCT__ "DMPlexVecGetClosure" 6437 /*@C 6438 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6439 6440 Not collective 6441 6442 Input Parameters: 6443 + dm - The DM 6444 . section - The section describing the layout in v, or NULL to use the default section 6445 . v - The local vector 6446 - point - The sieve point in the DM 6447 6448 Output Parameters: 6449 + csize - The number of values in the closure, or NULL 6450 - values - The array of values, which is a borrowed array and should not be freed 6451 6452 Fortran Notes: 6453 Since it returns an array, this routine is only available in Fortran 90, and you must 6454 include petsc.h90 in your code. 6455 6456 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6457 6458 Level: intermediate 6459 6460 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6461 @*/ 6462 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6463 { 6464 PetscScalar *array, *vArray; 6465 PetscInt *points = NULL; 6466 PetscInt offsets[32]; 6467 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 6468 PetscErrorCode ierr; 6469 6470 PetscFunctionBegin; 6471 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6472 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6473 if (!section) { 6474 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6475 } 6476 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6477 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6478 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6479 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6480 /* Compress out points not in the section */ 6481 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6482 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6483 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6484 points[q*2] = points[p]; 6485 points[q*2+1] = points[p+1]; 6486 ++q; 6487 } 6488 } 6489 numPoints = q; 6490 for (p = 0, size = 0; p < numPoints*2; p += 2) { 6491 PetscInt dof, fdof; 6492 6493 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6494 for (f = 0; f < numFields; ++f) { 6495 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6496 offsets[f+1] += fdof; 6497 } 6498 size += dof; 6499 } 6500 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6501 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 6502 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 6503 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 6504 for (p = 0; p < numPoints*2; p += 2) { 6505 PetscInt o = points[p+1]; 6506 PetscInt dof, off, d; 6507 PetscScalar *varr; 6508 6509 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6510 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 6511 varr = &vArray[off]; 6512 if (numFields) { 6513 PetscInt fdof, foff, fcomp, f, c; 6514 6515 for (f = 0, foff = 0; f < numFields; ++f) { 6516 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6517 if (o >= 0) { 6518 for (d = 0; d < fdof; ++d, ++offsets[f]) { 6519 array[offsets[f]] = varr[foff+d]; 6520 } 6521 } else { 6522 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6523 for (d = fdof/fcomp-1; d >= 0; --d) { 6524 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 6525 array[offsets[f]] = varr[foff+d*fcomp+c]; 6526 } 6527 } 6528 } 6529 foff += fdof; 6530 } 6531 } else { 6532 if (o >= 0) { 6533 for (d = 0; d < dof; ++d, ++offsets[0]) { 6534 array[offsets[0]] = varr[d]; 6535 } 6536 } else { 6537 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 6538 array[offsets[0]] = varr[d]; 6539 } 6540 } 6541 } 6542 } 6543 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6544 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 6545 if (csize) *csize = size; 6546 *values = array; 6547 PetscFunctionReturn(0); 6548 } 6549 6550 #undef __FUNCT__ 6551 #define __FUNCT__ "DMPlexVecRestoreClosure" 6552 /*@C 6553 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6554 6555 Not collective 6556 6557 Input Parameters: 6558 + dm - The DM 6559 . section - The section describing the layout in v, or NULL to use the default section 6560 . v - The local vector 6561 . point - The sieve point in the DM 6562 . csize - The number of values in the closure, or NULL 6563 - values - The array of values, which is a borrowed array and should not be freed 6564 6565 Fortran Notes: 6566 Since it returns an array, this routine is only available in Fortran 90, and you must 6567 include petsc.h90 in your code. 6568 6569 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6570 6571 Level: intermediate 6572 6573 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6574 @*/ 6575 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6576 { 6577 PetscInt size = 0; 6578 PetscErrorCode ierr; 6579 6580 PetscFunctionBegin; 6581 /* Should work without recalculating size */ 6582 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 6583 PetscFunctionReturn(0); 6584 } 6585 6586 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 6587 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 6588 6589 #undef __FUNCT__ 6590 #define __FUNCT__ "updatePoint_private" 6591 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6592 { 6593 PetscInt cdof; /* The number of constraints on this point */ 6594 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6595 PetscScalar *a; 6596 PetscInt off, cind = 0, k; 6597 PetscErrorCode ierr; 6598 6599 PetscFunctionBegin; 6600 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6601 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6602 a = &array[off]; 6603 if (!cdof || setBC) { 6604 if (orientation >= 0) { 6605 for (k = 0; k < dof; ++k) { 6606 fuse(&a[k], values[k]); 6607 } 6608 } else { 6609 for (k = 0; k < dof; ++k) { 6610 fuse(&a[k], values[dof-k-1]); 6611 } 6612 } 6613 } else { 6614 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6615 if (orientation >= 0) { 6616 for (k = 0; k < dof; ++k) { 6617 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6618 fuse(&a[k], values[k]); 6619 } 6620 } else { 6621 for (k = 0; k < dof; ++k) { 6622 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6623 fuse(&a[k], values[dof-k-1]); 6624 } 6625 } 6626 } 6627 PetscFunctionReturn(0); 6628 } 6629 6630 #undef __FUNCT__ 6631 #define __FUNCT__ "updatePointFields_private" 6632 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6633 { 6634 PetscScalar *a; 6635 PetscInt numFields, off, foff, f; 6636 PetscErrorCode ierr; 6637 6638 PetscFunctionBegin; 6639 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6640 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6641 a = &array[off]; 6642 for (f = 0, foff = 0; f < numFields; ++f) { 6643 PetscInt fdof, fcomp, fcdof; 6644 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6645 PetscInt cind = 0, k, c; 6646 6647 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6648 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6649 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6650 if (!fcdof || setBC) { 6651 if (orientation >= 0) { 6652 for (k = 0; k < fdof; ++k) { 6653 fuse(&a[foff+k], values[foffs[f]+k]); 6654 } 6655 } else { 6656 for (k = fdof/fcomp-1; k >= 0; --k) { 6657 for (c = 0; c < fcomp; ++c) { 6658 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6659 } 6660 } 6661 } 6662 } else { 6663 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6664 if (orientation >= 0) { 6665 for (k = 0; k < fdof; ++k) { 6666 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 6667 fuse(&a[foff+k], values[foffs[f]+k]); 6668 } 6669 } else { 6670 for (k = fdof/fcomp-1; k >= 0; --k) { 6671 for (c = 0; c < fcomp; ++c) { 6672 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 6673 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6674 } 6675 } 6676 } 6677 } 6678 foff += fdof; 6679 foffs[f] += fdof; 6680 } 6681 PetscFunctionReturn(0); 6682 } 6683 6684 #undef __FUNCT__ 6685 #define __FUNCT__ "DMPlexVecSetClosure" 6686 /*@C 6687 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6688 6689 Not collective 6690 6691 Input Parameters: 6692 + dm - The DM 6693 . section - The section describing the layout in v, or NULL to use the default section 6694 . v - The local vector 6695 . point - The sieve point in the DM 6696 . values - The array of values 6697 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6698 6699 Fortran Notes: 6700 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6701 6702 Level: intermediate 6703 6704 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6705 @*/ 6706 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6707 { 6708 PetscScalar *array; 6709 PetscInt *points = NULL; 6710 PetscInt offsets[32]; 6711 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 6712 PetscErrorCode ierr; 6713 6714 PetscFunctionBegin; 6715 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6716 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6717 if (!section) { 6718 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6719 } 6720 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6721 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6722 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6723 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6724 /* Compress out points not in the section */ 6725 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6726 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6727 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6728 points[q*2] = points[p]; 6729 points[q*2+1] = points[p+1]; 6730 ++q; 6731 } 6732 } 6733 numPoints = q; 6734 for (p = 0; p < numPoints*2; p += 2) { 6735 PetscInt fdof; 6736 6737 for (f = 0; f < numFields; ++f) { 6738 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6739 offsets[f+1] += fdof; 6740 } 6741 } 6742 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6743 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6744 if (numFields) { 6745 switch (mode) { 6746 case INSERT_VALUES: 6747 for (p = 0; p < numPoints*2; p += 2) { 6748 PetscInt o = points[p+1]; 6749 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 6750 } break; 6751 case INSERT_ALL_VALUES: 6752 for (p = 0; p < numPoints*2; p += 2) { 6753 PetscInt o = points[p+1]; 6754 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 6755 } break; 6756 case ADD_VALUES: 6757 for (p = 0; p < numPoints*2; p += 2) { 6758 PetscInt o = points[p+1]; 6759 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 6760 } break; 6761 case ADD_ALL_VALUES: 6762 for (p = 0; p < numPoints*2; p += 2) { 6763 PetscInt o = points[p+1]; 6764 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 6765 } break; 6766 default: 6767 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 6768 } 6769 } else { 6770 switch (mode) { 6771 case INSERT_VALUES: 6772 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6773 PetscInt o = points[p+1]; 6774 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6775 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 6776 } break; 6777 case INSERT_ALL_VALUES: 6778 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6779 PetscInt o = points[p+1]; 6780 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6781 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 6782 } break; 6783 case ADD_VALUES: 6784 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6785 PetscInt o = points[p+1]; 6786 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6787 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 6788 } break; 6789 case ADD_ALL_VALUES: 6790 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6791 PetscInt o = points[p+1]; 6792 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6793 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 6794 } break; 6795 default: 6796 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 6797 } 6798 } 6799 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6800 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6801 PetscFunctionReturn(0); 6802 } 6803 6804 #undef __FUNCT__ 6805 #define __FUNCT__ "DMPlexPrintMatSetValues" 6806 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], const PetscScalar values[]) 6807 { 6808 PetscMPIInt rank; 6809 PetscInt i, j; 6810 PetscErrorCode ierr; 6811 6812 PetscFunctionBegin; 6813 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 6814 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 6815 for (i = 0; i < numIndices; i++) { 6816 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 6817 } 6818 for (i = 0; i < numIndices; i++) { 6819 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 6820 for (j = 0; j < numIndices; j++) { 6821 #if defined(PETSC_USE_COMPLEX) 6822 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 6823 #else 6824 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 6825 #endif 6826 } 6827 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6828 } 6829 PetscFunctionReturn(0); 6830 } 6831 6832 #undef __FUNCT__ 6833 #define __FUNCT__ "indicesPoint_private" 6834 /* . off - The global offset of this point */ 6835 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 6836 { 6837 PetscInt dof; /* The number of unknowns on this point */ 6838 PetscInt cdof; /* The number of constraints on this point */ 6839 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6840 PetscInt cind = 0, k; 6841 PetscErrorCode ierr; 6842 6843 PetscFunctionBegin; 6844 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6845 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6846 if (!cdof || setBC) { 6847 if (orientation >= 0) { 6848 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 6849 } else { 6850 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 6851 } 6852 } else { 6853 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6854 if (orientation >= 0) { 6855 for (k = 0; k < dof; ++k) { 6856 if ((cind < cdof) && (k == cdofs[cind])) { 6857 /* Insert check for returning constrained indices */ 6858 indices[*loff+k] = -(off+k+1); 6859 ++cind; 6860 } else { 6861 indices[*loff+k] = off+k-cind; 6862 } 6863 } 6864 } else { 6865 for (k = 0; k < dof; ++k) { 6866 if ((cind < cdof) && (k == cdofs[cind])) { 6867 /* Insert check for returning constrained indices */ 6868 indices[*loff+dof-k-1] = -(off+k+1); 6869 ++cind; 6870 } else { 6871 indices[*loff+dof-k-1] = off+k-cind; 6872 } 6873 } 6874 } 6875 } 6876 *loff += dof; 6877 PetscFunctionReturn(0); 6878 } 6879 6880 #undef __FUNCT__ 6881 #define __FUNCT__ "indicesPointFields_private" 6882 /* . off - The global offset of this point */ 6883 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 6884 { 6885 PetscInt numFields, foff, f; 6886 PetscErrorCode ierr; 6887 6888 PetscFunctionBegin; 6889 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6890 for (f = 0, foff = 0; f < numFields; ++f) { 6891 PetscInt fdof, fcomp, cfdof; 6892 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6893 PetscInt cind = 0, k, c; 6894 6895 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6896 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6897 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6898 if (!cfdof || setBC) { 6899 if (orientation >= 0) { 6900 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 6901 } else { 6902 for (k = fdof/fcomp-1; k >= 0; --k) { 6903 for (c = 0; c < fcomp; ++c) { 6904 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 6905 } 6906 } 6907 } 6908 } else { 6909 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6910 if (orientation >= 0) { 6911 for (k = 0; k < fdof; ++k) { 6912 if ((cind < cfdof) && (k == fcdofs[cind])) { 6913 indices[foffs[f]+k] = -(off+foff+k+1); 6914 ++cind; 6915 } else { 6916 indices[foffs[f]+k] = off+foff+k-cind; 6917 } 6918 } 6919 } else { 6920 for (k = fdof/fcomp-1; k >= 0; --k) { 6921 for (c = 0; c < fcomp; ++c) { 6922 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 6923 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 6924 ++cind; 6925 } else { 6926 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 6927 } 6928 } 6929 } 6930 } 6931 } 6932 foff += fdof - cfdof; 6933 foffs[f] += fdof; 6934 } 6935 PetscFunctionReturn(0); 6936 } 6937 6938 #undef __FUNCT__ 6939 #define __FUNCT__ "DMPlexMatSetClosure" 6940 /*@C 6941 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 6942 6943 Not collective 6944 6945 Input Parameters: 6946 + dm - The DM 6947 . section - The section describing the layout in v, or NULL to use the default section 6948 . globalSection - The section describing the layout in v, or NULL to use the default section 6949 . A - The matrix 6950 . point - The sieve point in the DM 6951 . values - The array of values 6952 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6953 6954 Fortran Notes: 6955 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6956 6957 Level: intermediate 6958 6959 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 6960 @*/ 6961 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6962 { 6963 DM_Plex *mesh = (DM_Plex*) dm->data; 6964 PetscInt *points = NULL; 6965 PetscInt *indices; 6966 PetscInt offsets[32]; 6967 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 6968 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 6969 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 6970 PetscErrorCode ierr; 6971 6972 PetscFunctionBegin; 6973 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6974 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 6975 if (useDefault) { 6976 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6977 } 6978 if (useGlobalDefault) { 6979 if (useDefault) { 6980 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 6981 } else { 6982 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6983 } 6984 } 6985 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6986 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6987 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6988 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6989 /* Compress out points not in the section */ 6990 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6991 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6992 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6993 points[q*2] = points[p]; 6994 points[q*2+1] = points[p+1]; 6995 ++q; 6996 } 6997 } 6998 numPoints = q; 6999 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 7000 PetscInt fdof; 7001 7002 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7003 for (f = 0; f < numFields; ++f) { 7004 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7005 offsets[f+1] += fdof; 7006 } 7007 numIndices += dof; 7008 } 7009 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 7010 7011 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 7012 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 7013 if (numFields) { 7014 for (p = 0; p < numPoints*2; p += 2) { 7015 PetscInt o = points[p+1]; 7016 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 7017 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 7018 } 7019 } else { 7020 for (p = 0, off = 0; p < numPoints*2; p += 2) { 7021 PetscInt o = points[p+1]; 7022 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 7023 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 7024 } 7025 } 7026 if (useGlobalDefault && !useDefault) { 7027 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7028 } 7029 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 7030 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7031 if (ierr) { 7032 PetscMPIInt rank; 7033 PetscErrorCode ierr2; 7034 7035 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 7036 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7037 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 7038 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 7039 CHKERRQ(ierr); 7040 } 7041 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7042 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 7043 PetscFunctionReturn(0); 7044 } 7045 7046 #undef __FUNCT__ 7047 #define __FUNCT__ "DMPlexGetHybridBounds" 7048 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 7049 { 7050 DM_Plex *mesh = (DM_Plex*) dm->data; 7051 PetscInt dim; 7052 PetscErrorCode ierr; 7053 7054 PetscFunctionBegin; 7055 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7056 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7057 if (cMax) *cMax = mesh->hybridPointMax[dim]; 7058 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 7059 if (eMax) *eMax = mesh->hybridPointMax[1]; 7060 if (vMax) *vMax = mesh->hybridPointMax[0]; 7061 PetscFunctionReturn(0); 7062 } 7063 7064 #undef __FUNCT__ 7065 #define __FUNCT__ "DMPlexSetHybridBounds" 7066 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 7067 { 7068 DM_Plex *mesh = (DM_Plex*) dm->data; 7069 PetscInt dim; 7070 PetscErrorCode ierr; 7071 7072 PetscFunctionBegin; 7073 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7074 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7075 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 7076 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 7077 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 7078 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 7079 PetscFunctionReturn(0); 7080 } 7081 7082 #undef __FUNCT__ 7083 #define __FUNCT__ "DMPlexGetVTKCellHeight" 7084 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7085 { 7086 DM_Plex *mesh = (DM_Plex*) dm->data; 7087 7088 PetscFunctionBegin; 7089 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7090 PetscValidPointer(cellHeight, 2); 7091 *cellHeight = mesh->vtkCellHeight; 7092 PetscFunctionReturn(0); 7093 } 7094 7095 #undef __FUNCT__ 7096 #define __FUNCT__ "DMPlexSetVTKCellHeight" 7097 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7098 { 7099 DM_Plex *mesh = (DM_Plex*) dm->data; 7100 7101 PetscFunctionBegin; 7102 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7103 mesh->vtkCellHeight = cellHeight; 7104 PetscFunctionReturn(0); 7105 } 7106 7107 #undef __FUNCT__ 7108 #define __FUNCT__ "DMPlexCreateNumbering_Private" 7109 /* We can easily have a form that takes an IS instead */ 7110 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 7111 { 7112 PetscSection section, globalSection; 7113 PetscInt *numbers, p; 7114 PetscErrorCode ierr; 7115 7116 PetscFunctionBegin; 7117 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7118 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7119 for (p = pStart; p < pEnd; ++p) { 7120 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7121 } 7122 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7123 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7124 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 7125 for (p = pStart; p < pEnd; ++p) { 7126 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7127 } 7128 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7129 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7130 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7131 PetscFunctionReturn(0); 7132 } 7133 7134 #undef __FUNCT__ 7135 #define __FUNCT__ "DMPlexGetCellNumbering" 7136 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7137 { 7138 DM_Plex *mesh = (DM_Plex*) dm->data; 7139 PetscInt cellHeight, cStart, cEnd, cMax; 7140 PetscErrorCode ierr; 7141 7142 PetscFunctionBegin; 7143 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7144 if (!mesh->globalCellNumbers) { 7145 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7146 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 7147 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7148 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7149 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 7150 } 7151 *globalCellNumbers = mesh->globalCellNumbers; 7152 PetscFunctionReturn(0); 7153 } 7154 7155 #undef __FUNCT__ 7156 #define __FUNCT__ "DMPlexGetVertexNumbering" 7157 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7158 { 7159 DM_Plex *mesh = (DM_Plex*) dm->data; 7160 PetscInt vStart, vEnd, vMax; 7161 PetscErrorCode ierr; 7162 7163 PetscFunctionBegin; 7164 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7165 if (!mesh->globalVertexNumbers) { 7166 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7167 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 7168 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 7169 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 7170 } 7171 *globalVertexNumbers = mesh->globalVertexNumbers; 7172 PetscFunctionReturn(0); 7173 } 7174 7175 7176 #undef __FUNCT__ 7177 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 7178 /*@C 7179 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 7180 the local section and an SF describing the section point overlap. 7181 7182 Input Parameters: 7183 + s - The PetscSection for the local field layout 7184 . sf - The SF describing parallel layout of the section points 7185 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 7186 . label - The label specifying the points 7187 - labelValue - The label stratum specifying the points 7188 7189 Output Parameter: 7190 . gsection - The PetscSection for the global field layout 7191 7192 Note: This gives negative sizes and offsets to points not owned by this process 7193 7194 Level: developer 7195 7196 .seealso: PetscSectionCreate() 7197 @*/ 7198 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 7199 { 7200 PetscInt *neg; 7201 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 7202 PetscErrorCode ierr; 7203 7204 PetscFunctionBegin; 7205 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 7206 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 7207 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 7208 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 7209 /* Mark ghost points with negative dof */ 7210 for (p = pStart; p < pEnd; ++p) { 7211 PetscInt value; 7212 7213 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 7214 if (value != labelValue) continue; 7215 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 7216 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 7217 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 7218 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 7219 neg[p-pStart] = -(dof+1); 7220 } 7221 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 7222 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 7223 if (nroots >= 0) { 7224 if (nroots > pEnd - pStart) { 7225 PetscInt *tmpDof; 7226 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 7227 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 7228 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 7229 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 7230 for (p = pStart; p < pEnd; ++p) { 7231 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 7232 } 7233 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 7234 } else { 7235 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 7236 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 7237 } 7238 } 7239 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 7240 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7241 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 7242 7243 (*gsection)->atlasOff[p] = off; 7244 7245 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 7246 } 7247 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 7248 globalOff -= off; 7249 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7250 (*gsection)->atlasOff[p] += globalOff; 7251 7252 neg[p] = -((*gsection)->atlasOff[p]+1); 7253 } 7254 /* Put in negative offsets for ghost points */ 7255 if (nroots >= 0) { 7256 if (nroots > pEnd - pStart) { 7257 PetscInt *tmpOff; 7258 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 7259 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 7260 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 7261 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 7262 for (p = pStart; p < pEnd; ++p) { 7263 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 7264 } 7265 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 7266 } else { 7267 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 7268 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 7269 } 7270 } 7271 ierr = PetscFree(neg);CHKERRQ(ierr); 7272 PetscFunctionReturn(0); 7273 } 7274