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