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