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