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