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