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