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