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