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