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