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