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