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