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