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