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