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