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