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