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