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