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