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