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