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