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__ "DMPlexGetCoordinateSection" 6483 /*@ 6484 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6485 6486 Not Collective 6487 6488 Input Parameter: 6489 . dm - The DMPlex object 6490 6491 Output Parameter: 6492 . section - The PetscSection object 6493 6494 Level: intermediate 6495 6496 .keywords: mesh, coordinates 6497 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6498 @*/ 6499 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 6500 { 6501 DM cdm; 6502 PetscErrorCode ierr; 6503 6504 PetscFunctionBegin; 6505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6506 PetscValidPointer(section, 2); 6507 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6508 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 6509 PetscFunctionReturn(0); 6510 } 6511 6512 #undef __FUNCT__ 6513 #define __FUNCT__ "DMPlexSetCoordinateSection" 6514 /*@ 6515 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 6516 6517 Not Collective 6518 6519 Input Parameters: 6520 + dm - The DMPlex object 6521 - section - The PetscSection object 6522 6523 Level: intermediate 6524 6525 .keywords: mesh, coordinates 6526 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6527 @*/ 6528 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 6529 { 6530 DM cdm; 6531 PetscErrorCode ierr; 6532 6533 PetscFunctionBegin; 6534 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6535 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 6536 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6537 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 6538 PetscFunctionReturn(0); 6539 } 6540 6541 #undef __FUNCT__ 6542 #define __FUNCT__ "DMPlexGetConeSection" 6543 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 6544 { 6545 DM_Plex *mesh = (DM_Plex*) dm->data; 6546 6547 PetscFunctionBegin; 6548 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6549 if (section) *section = mesh->coneSection; 6550 PetscFunctionReturn(0); 6551 } 6552 6553 #undef __FUNCT__ 6554 #define __FUNCT__ "DMPlexGetCones" 6555 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 6556 { 6557 DM_Plex *mesh = (DM_Plex*) dm->data; 6558 6559 PetscFunctionBegin; 6560 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6561 if (cones) *cones = mesh->cones; 6562 PetscFunctionReturn(0); 6563 } 6564 6565 #undef __FUNCT__ 6566 #define __FUNCT__ "DMPlexGetConeOrientations" 6567 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 6568 { 6569 DM_Plex *mesh = (DM_Plex*) dm->data; 6570 6571 PetscFunctionBegin; 6572 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6573 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 6574 PetscFunctionReturn(0); 6575 } 6576 6577 /******************************** FEM Support **********************************/ 6578 6579 #undef __FUNCT__ 6580 #define __FUNCT__ "DMPlexVecGetClosure" 6581 /*@C 6582 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6583 6584 Not collective 6585 6586 Input Parameters: 6587 + dm - The DM 6588 . section - The section describing the layout in v, or NULL to use the default section 6589 . v - The local vector 6590 - point - The sieve point in the DM 6591 6592 Output Parameters: 6593 + csize - The number of values in the closure, or NULL 6594 - values - The array of values, which is a borrowed array and should not be freed 6595 6596 Fortran Notes: 6597 Since it returns an array, this routine is only available in Fortran 90, and you must 6598 include petsc.h90 in your code. 6599 6600 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6601 6602 Level: intermediate 6603 6604 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6605 @*/ 6606 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6607 { 6608 PetscSection clSection; 6609 IS clIndices; 6610 PetscScalar *array, *vArray; 6611 PetscInt *points = NULL; 6612 PetscInt offsets[32]; 6613 PetscInt depth, numFields, size = 0, numPoints, pStart, pEnd, p, q, f; 6614 PetscErrorCode ierr; 6615 6616 PetscFunctionBegin; 6617 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6618 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6619 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 6620 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clIndices);CHKERRQ(ierr); 6621 if (clSection) { 6622 const PetscInt *idx; 6623 PetscInt dof, off; 6624 6625 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 6626 if (csize) *csize = dof; 6627 if (values) { 6628 if (!*values) { 6629 ierr = DMGetWorkArray(dm, dof, PETSC_SCALAR, &array);CHKERRQ(ierr); 6630 *values = array; 6631 } else { 6632 array = *values; 6633 } 6634 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 6635 ierr = ISGetIndices(clIndices, &idx);CHKERRQ(ierr); 6636 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 6637 for (p = 0; p < dof; ++p) array[p] = vArray[idx[off+p]]; 6638 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 6639 ierr = ISRestoreIndices(clIndices, &idx);CHKERRQ(ierr); 6640 } 6641 PetscFunctionReturn(0); 6642 } 6643 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6644 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6645 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6646 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6647 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6648 if (depth == 1 && numFields < 2) { 6649 const PetscInt *cone, *coneO; 6650 6651 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6652 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6653 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6654 if (!values || !*values) { 6655 if ((point >= pStart) && (point < pEnd)) { 6656 PetscInt dof; 6657 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6658 size += dof; 6659 } 6660 for (p = 0; p < numPoints; ++p) { 6661 const PetscInt cp = cone[p]; 6662 PetscInt dof; 6663 6664 if ((cp < pStart) || (cp >= pEnd)) continue; 6665 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6666 size += dof; 6667 } 6668 if (!values) { 6669 if (csize) *csize = size; 6670 PetscFunctionReturn(0); 6671 } 6672 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 6673 } else { 6674 array = *values; 6675 } 6676 size = 0; 6677 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 6678 if ((point >= pStart) && (point < pEnd)) { 6679 PetscInt dof, off, d; 6680 PetscScalar *varr; 6681 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6682 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6683 varr = &vArray[off]; 6684 for (d = 0; d < dof; ++d, ++offsets[0]) { 6685 array[offsets[0]] = varr[d]; 6686 } 6687 size += dof; 6688 } 6689 for (p = 0; p < numPoints; ++p) { 6690 const PetscInt cp = cone[p]; 6691 PetscInt o = coneO[p]; 6692 PetscInt dof, off, d; 6693 PetscScalar *varr; 6694 6695 if ((cp < pStart) || (cp >= pEnd)) continue; 6696 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6697 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 6698 varr = &vArray[off]; 6699 if (o >= 0) { 6700 for (d = 0; d < dof; ++d, ++offsets[0]) { 6701 array[offsets[0]] = varr[d]; 6702 } 6703 } else { 6704 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 6705 array[offsets[0]] = varr[d]; 6706 } 6707 } 6708 size += dof; 6709 } 6710 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 6711 if (!*values) { 6712 if (csize) *csize = size; 6713 *values = array; 6714 } else { 6715 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 6716 *csize = size; 6717 } 6718 PetscFunctionReturn(0); 6719 } 6720 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6721 /* Compress out points not in the section */ 6722 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6723 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6724 points[q*2] = points[p]; 6725 points[q*2+1] = points[p+1]; 6726 ++q; 6727 } 6728 } 6729 numPoints = q; 6730 if (!values || !*values) { 6731 for (p = 0, size = 0; p < numPoints*2; p += 2) { 6732 PetscInt dof, fdof; 6733 6734 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6735 for (f = 0; f < numFields; ++f) { 6736 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6737 offsets[f+1] += fdof; 6738 } 6739 size += dof; 6740 } 6741 if (!values) { 6742 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6743 if (csize) *csize = size; 6744 PetscFunctionReturn(0); 6745 } 6746 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 6747 } else { 6748 array = *values; 6749 } 6750 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6751 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 6752 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 6753 for (p = 0; p < numPoints*2; p += 2) { 6754 PetscInt o = points[p+1]; 6755 PetscInt dof, off, d; 6756 PetscScalar *varr; 6757 6758 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6759 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 6760 varr = &vArray[off]; 6761 if (numFields) { 6762 PetscInt fdof, foff, fcomp, f, c; 6763 6764 for (f = 0, foff = 0; f < numFields; ++f) { 6765 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6766 if (o >= 0) { 6767 for (d = 0; d < fdof; ++d, ++offsets[f]) { 6768 array[offsets[f]] = varr[foff+d]; 6769 } 6770 } else { 6771 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6772 for (d = fdof/fcomp-1; d >= 0; --d) { 6773 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 6774 array[offsets[f]] = varr[foff+d*fcomp+c]; 6775 } 6776 } 6777 } 6778 foff += fdof; 6779 } 6780 } else { 6781 if (o >= 0) { 6782 for (d = 0; d < dof; ++d, ++offsets[0]) { 6783 array[offsets[0]] = varr[d]; 6784 } 6785 } else { 6786 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 6787 array[offsets[0]] = varr[d]; 6788 } 6789 } 6790 } 6791 } 6792 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6793 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 6794 if (!*values) { 6795 if (csize) *csize = size; 6796 *values = array; 6797 } else { 6798 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 6799 *csize = size; 6800 } 6801 PetscFunctionReturn(0); 6802 } 6803 6804 #undef __FUNCT__ 6805 #define __FUNCT__ "DMPlexVecRestoreClosure" 6806 /*@C 6807 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6808 6809 Not collective 6810 6811 Input Parameters: 6812 + dm - The DM 6813 . section - The section describing the layout in v, or NULL to use the default section 6814 . v - The local vector 6815 . point - The sieve point in the DM 6816 . csize - The number of values in the closure, or NULL 6817 - values - The array of values, which is a borrowed array and should not be freed 6818 6819 Fortran Notes: 6820 Since it returns an array, this routine is only available in Fortran 90, and you must 6821 include petsc.h90 in your code. 6822 6823 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6824 6825 Level: intermediate 6826 6827 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6828 @*/ 6829 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6830 { 6831 PetscInt size = 0; 6832 PetscErrorCode ierr; 6833 6834 PetscFunctionBegin; 6835 /* Should work without recalculating size */ 6836 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 6837 PetscFunctionReturn(0); 6838 } 6839 6840 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 6841 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 6842 6843 #undef __FUNCT__ 6844 #define __FUNCT__ "updatePoint_private" 6845 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6846 { 6847 PetscInt cdof; /* The number of constraints on this point */ 6848 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6849 PetscScalar *a; 6850 PetscInt off, cind = 0, k; 6851 PetscErrorCode ierr; 6852 6853 PetscFunctionBegin; 6854 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6855 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6856 a = &array[off]; 6857 if (!cdof || setBC) { 6858 if (orientation >= 0) { 6859 for (k = 0; k < dof; ++k) { 6860 fuse(&a[k], values[k]); 6861 } 6862 } else { 6863 for (k = 0; k < dof; ++k) { 6864 fuse(&a[k], values[dof-k-1]); 6865 } 6866 } 6867 } else { 6868 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6869 if (orientation >= 0) { 6870 for (k = 0; k < dof; ++k) { 6871 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6872 fuse(&a[k], values[k]); 6873 } 6874 } else { 6875 for (k = 0; k < dof; ++k) { 6876 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6877 fuse(&a[k], values[dof-k-1]); 6878 } 6879 } 6880 } 6881 PetscFunctionReturn(0); 6882 } 6883 6884 #undef __FUNCT__ 6885 #define __FUNCT__ "updatePointBC_private" 6886 PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6887 { 6888 PetscInt cdof; /* The number of constraints on this point */ 6889 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6890 PetscScalar *a; 6891 PetscInt off, cind = 0, k; 6892 PetscErrorCode ierr; 6893 6894 PetscFunctionBegin; 6895 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6896 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6897 a = &array[off]; 6898 if (cdof) { 6899 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6900 if (orientation >= 0) { 6901 for (k = 0; k < dof; ++k) { 6902 if ((cind < cdof) && (k == cdofs[cind])) { 6903 fuse(&a[k], values[k]); 6904 ++cind; 6905 } 6906 } 6907 } else { 6908 for (k = 0; k < dof; ++k) { 6909 if ((cind < cdof) && (k == cdofs[cind])) { 6910 fuse(&a[k], values[dof-k-1]); 6911 ++cind; 6912 } 6913 } 6914 } 6915 } 6916 PetscFunctionReturn(0); 6917 } 6918 6919 #undef __FUNCT__ 6920 #define __FUNCT__ "updatePointFields_private" 6921 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6922 { 6923 PetscScalar *a; 6924 PetscInt numFields, off, foff, f; 6925 PetscErrorCode ierr; 6926 6927 PetscFunctionBegin; 6928 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6929 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6930 a = &array[off]; 6931 for (f = 0, foff = 0; f < numFields; ++f) { 6932 PetscInt fdof, fcomp, fcdof; 6933 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6934 PetscInt cind = 0, k, c; 6935 6936 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6937 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6938 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6939 if (!fcdof || setBC) { 6940 if (orientation >= 0) { 6941 for (k = 0; k < fdof; ++k) { 6942 fuse(&a[foff+k], values[foffs[f]+k]); 6943 } 6944 } else { 6945 for (k = fdof/fcomp-1; k >= 0; --k) { 6946 for (c = 0; c < fcomp; ++c) { 6947 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6948 } 6949 } 6950 } 6951 } else { 6952 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6953 if (orientation >= 0) { 6954 for (k = 0; k < fdof; ++k) { 6955 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 6956 fuse(&a[foff+k], values[foffs[f]+k]); 6957 } 6958 } else { 6959 for (k = fdof/fcomp-1; k >= 0; --k) { 6960 for (c = 0; c < fcomp; ++c) { 6961 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 6962 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6963 } 6964 } 6965 } 6966 } 6967 foff += fdof; 6968 foffs[f] += fdof; 6969 } 6970 PetscFunctionReturn(0); 6971 } 6972 6973 #undef __FUNCT__ 6974 #define __FUNCT__ "updatePointFieldsBC_private" 6975 PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6976 { 6977 PetscScalar *a; 6978 PetscInt numFields, off, foff, f; 6979 PetscErrorCode ierr; 6980 6981 PetscFunctionBegin; 6982 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6983 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6984 a = &array[off]; 6985 for (f = 0, foff = 0; f < numFields; ++f) { 6986 PetscInt fdof, fcomp, fcdof; 6987 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6988 PetscInt cind = 0, k, c; 6989 6990 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6991 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6992 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6993 if (fcdof) { 6994 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6995 if (orientation >= 0) { 6996 for (k = 0; k < fdof; ++k) { 6997 if ((cind < fcdof) && (k == fcdofs[cind])) { 6998 fuse(&a[foff+k], values[foffs[f]+k]); 6999 ++cind; 7000 } 7001 } 7002 } else { 7003 for (k = fdof/fcomp-1; k >= 0; --k) { 7004 for (c = 0; c < fcomp; ++c) { 7005 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 7006 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 7007 ++cind; 7008 } 7009 } 7010 } 7011 } 7012 } 7013 foff += fdof; 7014 foffs[f] += fdof; 7015 } 7016 PetscFunctionReturn(0); 7017 } 7018 7019 #undef __FUNCT__ 7020 #define __FUNCT__ "DMPlexVecSetClosure" 7021 /*@C 7022 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 7023 7024 Not collective 7025 7026 Input Parameters: 7027 + dm - The DM 7028 . section - The section describing the layout in v, or NULL to use the default section 7029 . v - The local vector 7030 . point - The sieve point in the DM 7031 . values - The array of values 7032 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7033 7034 Fortran Notes: 7035 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7036 7037 Level: intermediate 7038 7039 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 7040 @*/ 7041 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 7042 { 7043 PetscScalar *array; 7044 PetscInt *points = NULL; 7045 PetscInt offsets[32]; 7046 PetscInt depth, numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 7047 PetscErrorCode ierr; 7048 7049 PetscFunctionBegin; 7050 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7051 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7052 if (!section) { 7053 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7054 } 7055 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7056 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7057 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7058 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7059 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7060 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 7061 const PetscInt *cone, *coneO; 7062 7063 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 7064 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 7065 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 7066 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 7067 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 7068 const PetscInt cp = !p ? point : cone[p-1]; 7069 const PetscInt o = !p ? 0 : coneO[p-1]; 7070 7071 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 7072 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 7073 /* ADD_VALUES */ 7074 { 7075 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7076 PetscScalar *a; 7077 PetscInt cdof, coff, cind = 0, k; 7078 7079 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 7080 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 7081 a = &array[coff]; 7082 if (!cdof) { 7083 if (o >= 0) { 7084 for (k = 0; k < dof; ++k) { 7085 a[k] += values[off+k]; 7086 } 7087 } else { 7088 for (k = 0; k < dof; ++k) { 7089 a[k] += values[off+dof-k-1]; 7090 } 7091 } 7092 } else { 7093 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 7094 if (o >= 0) { 7095 for (k = 0; k < dof; ++k) { 7096 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7097 a[k] += values[off+k]; 7098 } 7099 } else { 7100 for (k = 0; k < dof; ++k) { 7101 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7102 a[k] += values[off+dof-k-1]; 7103 } 7104 } 7105 } 7106 } 7107 } 7108 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 7109 PetscFunctionReturn(0); 7110 } 7111 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7112 /* Compress out points not in the section */ 7113 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7114 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7115 points[q*2] = points[p]; 7116 points[q*2+1] = points[p+1]; 7117 ++q; 7118 } 7119 } 7120 numPoints = q; 7121 for (p = 0; p < numPoints*2; p += 2) { 7122 PetscInt fdof; 7123 7124 for (f = 0; f < numFields; ++f) { 7125 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7126 offsets[f+1] += fdof; 7127 } 7128 } 7129 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 7130 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 7131 if (numFields) { 7132 switch (mode) { 7133 case INSERT_VALUES: 7134 for (p = 0; p < numPoints*2; p += 2) { 7135 PetscInt o = points[p+1]; 7136 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 7137 } break; 7138 case INSERT_ALL_VALUES: 7139 for (p = 0; p < numPoints*2; p += 2) { 7140 PetscInt o = points[p+1]; 7141 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 7142 } break; 7143 case INSERT_BC_VALUES: 7144 for (p = 0; p < numPoints*2; p += 2) { 7145 PetscInt o = points[p+1]; 7146 updatePointFieldsBC_private(section, points[p], offsets, insert, o, values, array); 7147 } break; 7148 case ADD_VALUES: 7149 for (p = 0; p < numPoints*2; p += 2) { 7150 PetscInt o = points[p+1]; 7151 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 7152 } break; 7153 case ADD_ALL_VALUES: 7154 for (p = 0; p < numPoints*2; p += 2) { 7155 PetscInt o = points[p+1]; 7156 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 7157 } break; 7158 default: 7159 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7160 } 7161 } else { 7162 switch (mode) { 7163 case INSERT_VALUES: 7164 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7165 PetscInt o = points[p+1]; 7166 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7167 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 7168 } break; 7169 case INSERT_ALL_VALUES: 7170 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7171 PetscInt o = points[p+1]; 7172 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7173 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 7174 } break; 7175 case INSERT_BC_VALUES: 7176 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7177 PetscInt o = points[p+1]; 7178 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7179 updatePointBC_private(section, points[p], dof, insert, o, &values[off], array); 7180 } break; 7181 case ADD_VALUES: 7182 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7183 PetscInt o = points[p+1]; 7184 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7185 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 7186 } break; 7187 case ADD_ALL_VALUES: 7188 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7189 PetscInt o = points[p+1]; 7190 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7191 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 7192 } break; 7193 default: 7194 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7195 } 7196 } 7197 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7198 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 7199 PetscFunctionReturn(0); 7200 } 7201 7202 #undef __FUNCT__ 7203 #define __FUNCT__ "DMPlexCreateClosureIndex" 7204 /*@ 7205 DMPlexCreateClosureIndex - Calculate an index for the given PetscSection for the closure operation on the DM 7206 7207 Not collective 7208 7209 Input Parameters: 7210 + dm - The DM 7211 - section - The section describing the layout in v, or NULL to use the default section 7212 7213 Note: 7214 This should greatly improve the performance of the closure operations, at the cost of additional memory. 7215 7216 Level: intermediate 7217 7218 .seealso DMPlexVecGetClosure(), DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7219 @*/ 7220 PetscErrorCode DMPlexCreateClosureIndex(DM dm, PetscSection section) 7221 { 7222 PetscSection closureSection; 7223 IS closureIS; 7224 PetscInt offsets[32], *clIndices; 7225 PetscInt depth, numFields, pStart, pEnd, point, clSize; 7226 PetscErrorCode ierr; 7227 7228 PetscFunctionBegin; 7229 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7230 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 7231 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7232 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7233 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7234 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7235 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) section), &closureSection);CHKERRQ(ierr); 7236 ierr = PetscSectionSetChart(closureSection, pStart, pEnd);CHKERRQ(ierr); 7237 for (point = pStart; point < pEnd; ++point) { 7238 PetscInt *points = NULL, numPoints, p, dof, cldof = 0; 7239 7240 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7241 for (p = 0; p < numPoints*2; p += 2) { 7242 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7243 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7244 cldof += dof; 7245 } 7246 } 7247 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7248 ierr = PetscSectionSetDof(closureSection, point, cldof);CHKERRQ(ierr); 7249 } 7250 ierr = PetscSectionSetUp(closureSection);CHKERRQ(ierr); 7251 ierr = PetscSectionGetStorageSize(closureSection, &clSize);CHKERRQ(ierr); 7252 ierr = PetscMalloc(clSize * sizeof(PetscInt), &clIndices);CHKERRQ(ierr); 7253 for (point = pStart; point < pEnd; ++point) { 7254 PetscInt *points = NULL, numPoints, p, q, cldof, cloff, fdof, f; 7255 7256 ierr = PetscSectionGetDof(closureSection, point, &cldof);CHKERRQ(ierr); 7257 ierr = PetscSectionGetOffset(closureSection, point, &cloff);CHKERRQ(ierr); 7258 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7259 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7260 /* Compress out points not in the section, and create field offsets */ 7261 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7262 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7263 points[q*2] = points[p]; 7264 points[q*2+1] = points[p+1]; 7265 for (f = 0; f < numFields; ++f) { 7266 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7267 offsets[f+1] += fdof; 7268 } 7269 ++q; 7270 } 7271 } 7272 numPoints = q; 7273 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 7274 if (numFields && offsets[numFields] != cldof) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], cldof); 7275 /* Create indices */ 7276 for (p = 0; p < numPoints*2; p += 2) { 7277 PetscInt o = points[p+1], dof, off, d; 7278 7279 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7280 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 7281 if (numFields) { 7282 PetscInt fdof, foff, fcomp, f, c; 7283 7284 for (f = 0, foff = 0; f < numFields; ++f) { 7285 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7286 if (o >= 0) { 7287 for (d = 0; d < fdof; ++d, ++offsets[f]) clIndices[cloff+offsets[f]] = off+foff+d; 7288 } else { 7289 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7290 for (d = fdof/fcomp-1; d >= 0; --d) { 7291 for (c = 0; c < fcomp; ++c, ++offsets[f]) clIndices[cloff+offsets[f]] = off+foff+d*fcomp+c; 7292 } 7293 } 7294 foff += fdof; 7295 } 7296 } else { 7297 if (o >= 0) for (d = 0; d < dof; ++d) clIndices[cloff+d] = off+d; 7298 else for (d = dof-1; d >= 0; --d) clIndices[cloff+d] = off+d; 7299 } 7300 } 7301 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7302 } 7303 ierr = ISCreateGeneral(PETSC_COMM_SELF, clSize, clIndices, PETSC_OWN_POINTER, &closureIS);CHKERRQ(ierr); 7304 ierr = PetscSectionSetClosureIndex(section, (PetscObject) dm, closureSection, closureIS); 7305 PetscFunctionReturn(0); 7306 } 7307 7308 #undef __FUNCT__ 7309 #define __FUNCT__ "DMPlexPrintMatSetValues" 7310 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], const PetscScalar values[]) 7311 { 7312 PetscMPIInt rank; 7313 PetscInt i, j; 7314 PetscErrorCode ierr; 7315 7316 PetscFunctionBegin; 7317 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 7318 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 7319 for (i = 0; i < numIndices; i++) { 7320 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 7321 } 7322 for (i = 0; i < numIndices; i++) { 7323 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 7324 for (j = 0; j < numIndices; j++) { 7325 #if defined(PETSC_USE_COMPLEX) 7326 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 7327 #else 7328 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 7329 #endif 7330 } 7331 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 7332 } 7333 PetscFunctionReturn(0); 7334 } 7335 7336 #undef __FUNCT__ 7337 #define __FUNCT__ "indicesPoint_private" 7338 /* . off - The global offset of this point */ 7339 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 7340 { 7341 PetscInt dof; /* The number of unknowns on this point */ 7342 PetscInt cdof; /* The number of constraints on this point */ 7343 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7344 PetscInt cind = 0, k; 7345 PetscErrorCode ierr; 7346 7347 PetscFunctionBegin; 7348 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 7349 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 7350 if (!cdof || setBC) { 7351 if (orientation >= 0) { 7352 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 7353 } else { 7354 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 7355 } 7356 } else { 7357 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 7358 if (orientation >= 0) { 7359 for (k = 0; k < dof; ++k) { 7360 if ((cind < cdof) && (k == cdofs[cind])) { 7361 /* Insert check for returning constrained indices */ 7362 indices[*loff+k] = -(off+k+1); 7363 ++cind; 7364 } else { 7365 indices[*loff+k] = off+k-cind; 7366 } 7367 } 7368 } else { 7369 for (k = 0; k < dof; ++k) { 7370 if ((cind < cdof) && (k == cdofs[cind])) { 7371 /* Insert check for returning constrained indices */ 7372 indices[*loff+dof-k-1] = -(off+k+1); 7373 ++cind; 7374 } else { 7375 indices[*loff+dof-k-1] = off+k-cind; 7376 } 7377 } 7378 } 7379 } 7380 *loff += dof; 7381 PetscFunctionReturn(0); 7382 } 7383 7384 #undef __FUNCT__ 7385 #define __FUNCT__ "indicesPointFields_private" 7386 /* . off - The global offset of this point */ 7387 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 7388 { 7389 PetscInt numFields, foff, f; 7390 PetscErrorCode ierr; 7391 7392 PetscFunctionBegin; 7393 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7394 for (f = 0, foff = 0; f < numFields; ++f) { 7395 PetscInt fdof, fcomp, cfdof; 7396 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 7397 PetscInt cind = 0, k, c; 7398 7399 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7400 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 7401 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 7402 if (!cfdof || setBC) { 7403 if (orientation >= 0) { 7404 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 7405 } else { 7406 for (k = fdof/fcomp-1; k >= 0; --k) { 7407 for (c = 0; c < fcomp; ++c) { 7408 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 7409 } 7410 } 7411 } 7412 } else { 7413 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 7414 if (orientation >= 0) { 7415 for (k = 0; k < fdof; ++k) { 7416 if ((cind < cfdof) && (k == fcdofs[cind])) { 7417 indices[foffs[f]+k] = -(off+foff+k+1); 7418 ++cind; 7419 } else { 7420 indices[foffs[f]+k] = off+foff+k-cind; 7421 } 7422 } 7423 } else { 7424 for (k = fdof/fcomp-1; k >= 0; --k) { 7425 for (c = 0; c < fcomp; ++c) { 7426 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 7427 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 7428 ++cind; 7429 } else { 7430 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 7431 } 7432 } 7433 } 7434 } 7435 } 7436 foff += fdof - cfdof; 7437 foffs[f] += fdof; 7438 } 7439 PetscFunctionReturn(0); 7440 } 7441 7442 #undef __FUNCT__ 7443 #define __FUNCT__ "DMPlexMatSetClosure" 7444 /*@C 7445 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7446 7447 Not collective 7448 7449 Input Parameters: 7450 + dm - The DM 7451 . section - The section describing the layout in v 7452 . globalSection - The section describing the layout in v 7453 . A - The matrix 7454 . point - The sieve point in the DM 7455 . values - The array of values 7456 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7457 7458 Fortran Notes: 7459 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7460 7461 Level: intermediate 7462 7463 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 7464 @*/ 7465 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7466 { 7467 DM_Plex *mesh = (DM_Plex*) dm->data; 7468 PetscInt *points = NULL; 7469 PetscInt *indices; 7470 PetscInt offsets[32]; 7471 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 7472 PetscErrorCode ierr; 7473 7474 PetscFunctionBegin; 7475 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7476 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7477 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7478 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7479 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7480 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7481 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7482 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7483 /* Compress out points not in the section */ 7484 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7485 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7486 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7487 points[q*2] = points[p]; 7488 points[q*2+1] = points[p+1]; 7489 ++q; 7490 } 7491 } 7492 numPoints = q; 7493 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 7494 PetscInt fdof; 7495 7496 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7497 for (f = 0; f < numFields; ++f) { 7498 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7499 offsets[f+1] += fdof; 7500 } 7501 numIndices += dof; 7502 } 7503 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 7504 7505 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 7506 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 7507 if (numFields) { 7508 for (p = 0; p < numPoints*2; p += 2) { 7509 PetscInt o = points[p+1]; 7510 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 7511 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 7512 } 7513 } else { 7514 for (p = 0, off = 0; p < numPoints*2; p += 2) { 7515 PetscInt o = points[p+1]; 7516 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 7517 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 7518 } 7519 } 7520 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 7521 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7522 if (ierr) { 7523 PetscMPIInt rank; 7524 PetscErrorCode ierr2; 7525 7526 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 7527 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7528 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 7529 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 7530 CHKERRQ(ierr); 7531 } 7532 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7533 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 7534 PetscFunctionReturn(0); 7535 } 7536 7537 #undef __FUNCT__ 7538 #define __FUNCT__ "DMPlexGetHybridBounds" 7539 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 7540 { 7541 DM_Plex *mesh = (DM_Plex*) dm->data; 7542 PetscInt dim; 7543 PetscErrorCode ierr; 7544 7545 PetscFunctionBegin; 7546 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7547 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7548 if (cMax) *cMax = mesh->hybridPointMax[dim]; 7549 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 7550 if (eMax) *eMax = mesh->hybridPointMax[1]; 7551 if (vMax) *vMax = mesh->hybridPointMax[0]; 7552 PetscFunctionReturn(0); 7553 } 7554 7555 #undef __FUNCT__ 7556 #define __FUNCT__ "DMPlexSetHybridBounds" 7557 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 7558 { 7559 DM_Plex *mesh = (DM_Plex*) dm->data; 7560 PetscInt dim; 7561 PetscErrorCode ierr; 7562 7563 PetscFunctionBegin; 7564 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7565 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7566 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 7567 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 7568 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 7569 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 7570 PetscFunctionReturn(0); 7571 } 7572 7573 #undef __FUNCT__ 7574 #define __FUNCT__ "DMPlexGetVTKCellHeight" 7575 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7576 { 7577 DM_Plex *mesh = (DM_Plex*) dm->data; 7578 7579 PetscFunctionBegin; 7580 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7581 PetscValidPointer(cellHeight, 2); 7582 *cellHeight = mesh->vtkCellHeight; 7583 PetscFunctionReturn(0); 7584 } 7585 7586 #undef __FUNCT__ 7587 #define __FUNCT__ "DMPlexSetVTKCellHeight" 7588 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7589 { 7590 DM_Plex *mesh = (DM_Plex*) dm->data; 7591 7592 PetscFunctionBegin; 7593 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7594 mesh->vtkCellHeight = cellHeight; 7595 PetscFunctionReturn(0); 7596 } 7597 7598 #undef __FUNCT__ 7599 #define __FUNCT__ "DMPlexCreateNumbering_Private" 7600 /* We can easily have a form that takes an IS instead */ 7601 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 7602 { 7603 PetscSection section, globalSection; 7604 PetscInt *numbers, p; 7605 PetscErrorCode ierr; 7606 7607 PetscFunctionBegin; 7608 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7609 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7610 for (p = pStart; p < pEnd; ++p) { 7611 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7612 } 7613 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7614 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7615 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 7616 for (p = pStart; p < pEnd; ++p) { 7617 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7618 } 7619 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7620 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7621 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7622 PetscFunctionReturn(0); 7623 } 7624 7625 #undef __FUNCT__ 7626 #define __FUNCT__ "DMPlexGetCellNumbering" 7627 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7628 { 7629 DM_Plex *mesh = (DM_Plex*) dm->data; 7630 PetscInt cellHeight, cStart, cEnd, cMax; 7631 PetscErrorCode ierr; 7632 7633 PetscFunctionBegin; 7634 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7635 if (!mesh->globalCellNumbers) { 7636 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7637 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 7638 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7639 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7640 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 7641 } 7642 *globalCellNumbers = mesh->globalCellNumbers; 7643 PetscFunctionReturn(0); 7644 } 7645 7646 #undef __FUNCT__ 7647 #define __FUNCT__ "DMPlexGetVertexNumbering" 7648 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7649 { 7650 DM_Plex *mesh = (DM_Plex*) dm->data; 7651 PetscInt vStart, vEnd, vMax; 7652 PetscErrorCode ierr; 7653 7654 PetscFunctionBegin; 7655 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7656 if (!mesh->globalVertexNumbers) { 7657 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7658 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 7659 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 7660 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 7661 } 7662 *globalVertexNumbers = mesh->globalVertexNumbers; 7663 PetscFunctionReturn(0); 7664 } 7665 7666 7667 #undef __FUNCT__ 7668 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 7669 /*@C 7670 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 7671 the local section and an SF describing the section point overlap. 7672 7673 Input Parameters: 7674 + s - The PetscSection for the local field layout 7675 . sf - The SF describing parallel layout of the section points 7676 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 7677 . label - The label specifying the points 7678 - labelValue - The label stratum specifying the points 7679 7680 Output Parameter: 7681 . gsection - The PetscSection for the global field layout 7682 7683 Note: This gives negative sizes and offsets to points not owned by this process 7684 7685 Level: developer 7686 7687 .seealso: PetscSectionCreate() 7688 @*/ 7689 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 7690 { 7691 PetscInt *neg = NULL, *tmpOff = NULL; 7692 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 7693 PetscErrorCode ierr; 7694 7695 PetscFunctionBegin; 7696 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 7697 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 7698 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 7699 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 7700 if (nroots >= 0) { 7701 if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart); 7702 ierr = PetscMalloc(nroots * sizeof(PetscInt), &neg);CHKERRQ(ierr); 7703 ierr = PetscMemzero(neg, nroots * sizeof(PetscInt));CHKERRQ(ierr); 7704 if (nroots > pEnd-pStart) { 7705 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 7706 ierr = PetscMemzero(tmpOff, nroots * sizeof(PetscInt));CHKERRQ(ierr); 7707 } else { 7708 tmpOff = &(*gsection)->atlasDof[-pStart]; 7709 } 7710 } 7711 /* Mark ghost points with negative dof */ 7712 for (p = pStart; p < pEnd; ++p) { 7713 PetscInt value; 7714 7715 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 7716 if (value != labelValue) continue; 7717 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 7718 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 7719 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 7720 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 7721 if (neg) neg[p] = -(dof+1); 7722 } 7723 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 7724 if (nroots >= 0) { 7725 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 7726 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 7727 if (nroots > pEnd-pStart) { 7728 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} 7729 } 7730 } 7731 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 7732 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7733 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 7734 (*gsection)->atlasOff[p] = off; 7735 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 7736 } 7737 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 7738 globalOff -= off; 7739 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7740 (*gsection)->atlasOff[p] += globalOff; 7741 if (neg) neg[p] = -((*gsection)->atlasOff[p]+1); 7742 } 7743 /* Put in negative offsets for ghost points */ 7744 if (nroots >= 0) { 7745 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 7746 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 7747 if (nroots > pEnd-pStart) { 7748 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} 7749 } 7750 } 7751 if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);} 7752 ierr = PetscFree(neg);CHKERRQ(ierr); 7753 PetscFunctionReturn(0); 7754 } 7755