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