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