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