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_Distribute, 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 #include <parmetis.h> 2471 2472 #undef __FUNCT__ 2473 #define __FUNCT__ "DMPlexPartition_ParMetis" 2474 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2475 { 2476 MPI_Comm comm; 2477 PetscInt nvtxs = numVertices; // The number of vertices in full graph 2478 PetscInt *vtxdist; // Distribution of vertices across processes 2479 PetscInt *xadj = start; // Start of edge list for each vertex 2480 PetscInt *adjncy = adjacency; // Edge lists for all vertices 2481 PetscInt *vwgt = NULL; // Vertex weights 2482 PetscInt *adjwgt = NULL; // Edge weights 2483 PetscInt wgtflag = 0; // Indicates which weights are present 2484 PetscInt numflag = 0; // Indicates initial offset (0 or 1) 2485 PetscInt ncon = 1; // The number of weights per vertex 2486 PetscInt nparts; // The number of partitions 2487 PetscReal *tpwgts; // The fraction of vertex weights assigned to each partition 2488 PetscReal *ubvec; // The balance intolerance for vertex weights 2489 PetscInt options[5]; // Options 2490 // Outputs 2491 PetscInt edgeCut; // The number of edges cut by the partition 2492 PetscInt *assignment, *points; 2493 PetscMPIInt commSize, rank, p, v, i; 2494 PetscErrorCode ierr; 2495 2496 PetscFunctionBegin; 2497 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 2498 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2499 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2500 if (!numVertices) { 2501 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2502 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2503 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2504 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2505 PetscFunctionReturn(0); 2506 } 2507 nparts = commSize; 2508 options[0] = 0; /* Use all defaults */ 2509 /* Calculate vertex distribution */ 2510 ierr = PetscMalloc4(nparts+1,PetscInt,&vtxdist,nparts*ncon,PetscReal,&tpwgts,ncon,PetscReal,&ubvec,nvtxs,PetscInt,&assignment);CHKERRQ(ierr); 2511 vtxdist[0] = 0; 2512 ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 2513 for (p = 2; p <= nparts; ++p) { 2514 vtxdist[p] += vtxdist[p-1]; 2515 } 2516 /* Calculate weights */ 2517 for (p = 0; p < nparts; ++p) { 2518 tpwgts[p] = 1.0/nparts; 2519 } 2520 ubvec[0] = 1.05; 2521 2522 if (nparts == 1) { 2523 ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt)); 2524 } else { 2525 if (vtxdist[1] == vtxdist[nparts]) { 2526 if (!rank) { 2527 PetscStackCallStandard(METIS_PartGraphKway, (&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment)); 2528 } 2529 } else { 2530 PetscStackCallStandard(ParMETIS_V3_PartKway, (vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm)); 2531 } 2532 } 2533 /* Convert to PetscSection+IS */ 2534 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2535 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2536 for (v = 0; v < nvtxs; ++v) { 2537 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2538 } 2539 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2540 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2541 for (p = 0, i = 0; p < commSize; ++p) { 2542 for (v = 0; v < nvtxs; ++v) { 2543 if (assignment[v] == p) points[i++] = v; 2544 } 2545 } 2546 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2547 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2548 ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 2549 PetscFunctionReturn(0); 2550 } 2551 #endif 2552 2553 #undef __FUNCT__ 2554 #define __FUNCT__ "DMPlexEnlargePartition" 2555 /* Expand the partition by BFS on the adjacency graph */ 2556 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2557 { 2558 PetscHashI h; 2559 const PetscInt *points; 2560 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2561 PetscInt pStart, pEnd, part, q; 2562 PetscErrorCode ierr; 2563 2564 PetscFunctionBegin; 2565 PetscHashICreate(h); 2566 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2567 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2568 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2569 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2570 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2571 for (part = pStart; part < pEnd; ++part) { 2572 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2573 2574 PetscHashIClear(h); 2575 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2576 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2577 /* Add all existing points to h */ 2578 for (p = 0; p < numPoints; ++p) { 2579 const PetscInt point = points[off+p]; 2580 PetscHashIAdd(h, point, 1); 2581 } 2582 PetscHashISize(h, nP); 2583 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2584 /* Add all points in next BFS level */ 2585 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2586 for (p = 0; p < numPoints; ++p) { 2587 const PetscInt point = points[off+p]; 2588 PetscInt s = start[point], e = start[point+1], a; 2589 2590 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2591 } 2592 PetscHashISize(h, numNewPoints); 2593 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2594 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2595 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2596 totPoints += numNewPoints; 2597 } 2598 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2599 PetscHashIDestroy(h); 2600 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2601 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2602 for (part = pStart, q = 0; part < pEnd; ++part) { 2603 PetscInt numPoints, p; 2604 2605 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2606 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2607 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2608 } 2609 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2610 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2611 PetscFunctionReturn(0); 2612 } 2613 2614 #undef __FUNCT__ 2615 #define __FUNCT__ "DMPlexCreatePartition" 2616 /* 2617 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2618 2619 Collective on DM 2620 2621 Input Parameters: 2622 + dm - The DM 2623 . height - The height for points in the partition 2624 - enlarge - Expand each partition with neighbors 2625 2626 Output Parameters: 2627 + partSection - The PetscSection giving the division of points by partition 2628 . partition - The list of points by partition 2629 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2630 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2631 2632 Level: developer 2633 2634 .seealso DMPlexDistribute() 2635 */ 2636 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2637 { 2638 PetscMPIInt size; 2639 PetscErrorCode ierr; 2640 2641 PetscFunctionBegin; 2642 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2643 2644 *origPartSection = NULL; 2645 *origPartition = NULL; 2646 if (size == 1) { 2647 PetscInt *points; 2648 PetscInt cStart, cEnd, c; 2649 2650 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2651 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2652 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2653 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2654 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2655 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2656 for (c = cStart; c < cEnd; ++c) points[c] = c; 2657 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2658 PetscFunctionReturn(0); 2659 } 2660 if (height == 0) { 2661 PetscInt numVertices; 2662 PetscInt *start = NULL; 2663 PetscInt *adjacency = NULL; 2664 2665 ierr = DMPlexCreateNeighborCSR(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2666 if (1) { 2667 #if defined(PETSC_HAVE_CHACO) 2668 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2669 #endif 2670 } else { 2671 #if defined(PETSC_HAVE_PARMETIS) 2672 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2673 #endif 2674 } 2675 if (enlarge) { 2676 *origPartSection = *partSection; 2677 *origPartition = *partition; 2678 2679 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2680 } 2681 ierr = PetscFree(start);CHKERRQ(ierr); 2682 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2683 # if 0 2684 } else if (height == 1) { 2685 /* Build the dual graph for faces and partition the hypergraph */ 2686 PetscInt numEdges; 2687 2688 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2689 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2690 destroyCSR(numEdges, start, adjacency); 2691 #endif 2692 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2693 PetscFunctionReturn(0); 2694 } 2695 2696 #undef __FUNCT__ 2697 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2698 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2699 { 2700 /* const PetscInt height = 0; */ 2701 const PetscInt *partArray; 2702 PetscInt *allPoints, *packPoints; 2703 PetscInt rStart, rEnd, rank, pStart, pEnd, newSize; 2704 PetscErrorCode ierr; 2705 PetscBT bt; 2706 PetscSegBuffer segpack,segpart; 2707 2708 PetscFunctionBegin; 2709 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2710 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2711 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2712 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2713 ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 2714 ierr = PetscBTCreate(pEnd-pStart,&bt);CHKERRQ(ierr); 2715 ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpack);CHKERRQ(ierr); 2716 ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpart);CHKERRQ(ierr); 2717 for (rank = rStart; rank < rEnd; ++rank) { 2718 PetscInt partSize = 0, numPoints, offset, p, *PETSC_RESTRICT placePoints; 2719 2720 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2721 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2722 for (p = 0; p < numPoints; ++p) { 2723 PetscInt point = partArray[offset+p], closureSize, c; 2724 PetscInt *closure = NULL; 2725 2726 /* TODO Include support for height > 0 case */ 2727 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2728 for (c=0; c<closureSize; c++) { 2729 PetscInt cpoint = closure[c*2]; 2730 if (!PetscBTLookupSet(bt,cpoint-pStart)) { 2731 PetscInt *PETSC_RESTRICT pt; 2732 partSize++; 2733 ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 2734 *pt = cpoint; 2735 } 2736 } 2737 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2738 } 2739 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 2740 ierr = PetscSegBufferGetInts(segpack,partSize,&placePoints);CHKERRQ(ierr); 2741 ierr = PetscSegBufferExtractTo(segpart,placePoints);CHKERRQ(ierr); 2742 ierr = PetscSortInt(partSize,placePoints);CHKERRQ(ierr); 2743 for (p=0; p<partSize; p++) {ierr = PetscBTClear(bt,placePoints[p]-pStart);CHKERRQ(ierr);} 2744 } 2745 ierr = PetscBTDestroy(&bt);CHKERRQ(ierr); 2746 ierr = PetscSegBufferDestroy(&segpart);CHKERRQ(ierr); 2747 2748 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 2749 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 2750 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 2751 2752 ierr = PetscSegBufferExtractInPlace(segpack,&packPoints);CHKERRQ(ierr); 2753 for (rank = rStart; rank < rEnd; ++rank) { 2754 PetscInt numPoints, offset; 2755 2756 ierr = PetscSectionGetDof(*section, rank, &numPoints);CHKERRQ(ierr); 2757 ierr = PetscSectionGetOffset(*section, rank, &offset);CHKERRQ(ierr); 2758 ierr = PetscMemcpy(&allPoints[offset], packPoints, numPoints * sizeof(PetscInt));CHKERRQ(ierr); 2759 packPoints += numPoints; 2760 } 2761 2762 ierr = PetscSegBufferDestroy(&segpack);CHKERRQ(ierr); 2763 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 2764 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2765 PetscFunctionReturn(0); 2766 } 2767 2768 #undef __FUNCT__ 2769 #define __FUNCT__ "DMPlexDistributeField" 2770 /* 2771 Input Parameters: 2772 . originalSection 2773 , originalVec 2774 2775 Output Parameters: 2776 . newSection 2777 . newVec 2778 */ 2779 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 2780 { 2781 PetscSF fieldSF; 2782 PetscInt *remoteOffsets, fieldSize; 2783 PetscScalar *originalValues, *newValues; 2784 PetscErrorCode ierr; 2785 2786 PetscFunctionBegin; 2787 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 2788 2789 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 2790 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 2791 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 2792 2793 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 2794 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 2795 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 2796 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 2797 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 2798 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 2799 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 2800 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 2801 PetscFunctionReturn(0); 2802 } 2803 2804 #undef __FUNCT__ 2805 #define __FUNCT__ "DMPlexDistribute" 2806 /*@C 2807 DMPlexDistribute - Distributes the mesh and any associated sections. 2808 2809 Not Collective 2810 2811 Input Parameter: 2812 + dm - The original DMPlex object 2813 . partitioner - The partitioning package, or NULL for the default 2814 - overlap - The overlap of partitions, 0 is the default 2815 2816 Output Parameter: 2817 . parallelMesh - The distributed DMPlex object, or NULL 2818 2819 Note: If the mesh was not distributed, the return value is NULL 2820 2821 Level: intermediate 2822 2823 .keywords: mesh, elements 2824 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 2825 @*/ 2826 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 2827 { 2828 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 2829 MPI_Comm comm; 2830 const PetscInt height = 0; 2831 PetscInt dim, numRemoteRanks; 2832 IS origCellPart, cellPart, part; 2833 PetscSection origCellPartSection, cellPartSection, partSection; 2834 PetscSFNode *remoteRanks; 2835 PetscSF partSF, pointSF, coneSF; 2836 ISLocalToGlobalMapping renumbering; 2837 PetscSection originalConeSection, newConeSection; 2838 PetscInt *remoteOffsets; 2839 PetscInt *cones, *newCones, newConesSize; 2840 PetscBool flg; 2841 PetscMPIInt rank, numProcs, p; 2842 PetscErrorCode ierr; 2843 2844 PetscFunctionBegin; 2845 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2846 PetscValidPointer(dmParallel,4); 2847 2848 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 2849 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2850 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2851 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 2852 2853 *dmParallel = NULL; 2854 if (numProcs == 1) PetscFunctionReturn(0); 2855 2856 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2857 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 2858 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 2859 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 2860 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 2861 if (!rank) numRemoteRanks = numProcs; 2862 else numRemoteRanks = 0; 2863 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 2864 for (p = 0; p < numRemoteRanks; ++p) { 2865 remoteRanks[p].rank = p; 2866 remoteRanks[p].index = 0; 2867 } 2868 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 2869 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 2870 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 2871 if (flg) { 2872 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 2873 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2874 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 2875 if (origCellPart) { 2876 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 2877 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2878 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 2879 } 2880 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 2881 } 2882 /* Close the partition over the mesh */ 2883 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 2884 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 2885 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 2886 /* Create new mesh */ 2887 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 2888 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 2889 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 2890 pmesh = (DM_Plex*) (*dmParallel)->data; 2891 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 2892 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 2893 if (flg) { 2894 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 2895 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2896 ierr = ISView(part, NULL);CHKERRQ(ierr); 2897 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 2898 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 2899 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 2900 } 2901 /* Distribute cone section */ 2902 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 2903 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 2904 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 2905 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 2906 { 2907 PetscInt pStart, pEnd, p; 2908 2909 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 2910 for (p = pStart; p < pEnd; ++p) { 2911 PetscInt coneSize; 2912 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 2913 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 2914 } 2915 } 2916 /* Communicate and renumber cones */ 2917 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 2918 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2919 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 2920 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2921 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2922 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 2923 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 2924 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 2925 if (flg) { 2926 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 2927 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2928 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 2929 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2930 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 2931 } 2932 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 2933 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 2934 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2935 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 2936 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 2937 /* Create supports and stratify sieve */ 2938 { 2939 PetscInt pStart, pEnd; 2940 2941 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2942 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2943 } 2944 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 2945 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 2946 /* Distribute Coordinates */ 2947 { 2948 PetscSection originalCoordSection, newCoordSection; 2949 Vec originalCoordinates, newCoordinates; 2950 const char *name; 2951 2952 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 2953 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 2954 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 2955 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 2956 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 2957 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 2958 2959 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 2960 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 2961 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 2962 } 2963 /* Distribute labels */ 2964 { 2965 DMLabel next = mesh->labels, newNext = pmesh->labels; 2966 PetscInt numLabels = 0, l; 2967 2968 /* Bcast number of labels */ 2969 while (next) { 2970 ++numLabels; next = next->next; 2971 } 2972 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 2973 next = mesh->labels; 2974 for (l = 0; l < numLabels; ++l) { 2975 DMLabel newLabel; 2976 const PetscInt *partArray; 2977 char *name; 2978 PetscInt *stratumSizes = NULL, *points = NULL; 2979 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 2980 PetscInt nameSize, s, p; 2981 PetscBool isdepth; 2982 size_t len = 0; 2983 2984 /* Bcast name (could filter for no points) */ 2985 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 2986 nameSize = len; 2987 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 2988 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 2989 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 2990 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 2991 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 2992 if (isdepth) { /* skip because "depth" is not distributed */ 2993 ierr = PetscFree(name);CHKERRQ(ierr); 2994 if (!rank) next = next->next; 2995 continue; 2996 } 2997 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 2998 newLabel->name = name; 2999 /* Bcast numStrata (could filter for no points in stratum) */ 3000 if (!rank) newLabel->numStrata = next->numStrata; 3001 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3002 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3003 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3004 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3005 /* Bcast stratumValues (could filter for no points in stratum) */ 3006 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3007 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3008 /* Find size on each process and Scatter */ 3009 if (!rank) { 3010 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3011 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3012 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3013 for (s = 0; s < next->numStrata; ++s) { 3014 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3015 const PetscInt point = next->points[p]; 3016 PetscInt proc; 3017 3018 for (proc = 0; proc < numProcs; ++proc) { 3019 PetscInt dof, off, pPart; 3020 3021 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3022 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3023 for (pPart = off; pPart < off+dof; ++pPart) { 3024 if (partArray[pPart] == point) { 3025 ++stratumSizes[proc*next->numStrata+s]; 3026 break; 3027 } 3028 } 3029 } 3030 } 3031 } 3032 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3033 } 3034 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3035 /* Calculate stratumOffsets */ 3036 newLabel->stratumOffsets[0] = 0; 3037 for (s = 0; s < newLabel->numStrata; ++s) { 3038 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3039 } 3040 /* Pack points and Scatter */ 3041 if (!rank) { 3042 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3043 displs[0] = 0; 3044 for (p = 0; p < numProcs; ++p) { 3045 sendcnts[p] = 0; 3046 for (s = 0; s < next->numStrata; ++s) { 3047 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3048 } 3049 offsets[p] = displs[p]; 3050 displs[p+1] = displs[p] + sendcnts[p]; 3051 } 3052 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3053 for (s = 0; s < next->numStrata; ++s) { 3054 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3055 const PetscInt point = next->points[p]; 3056 PetscInt proc; 3057 3058 for (proc = 0; proc < numProcs; ++proc) { 3059 PetscInt dof, off, pPart; 3060 3061 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3062 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3063 for (pPart = off; pPart < off+dof; ++pPart) { 3064 if (partArray[pPart] == point) { 3065 points[offsets[proc]++] = point; 3066 break; 3067 } 3068 } 3069 } 3070 } 3071 } 3072 } 3073 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3074 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3075 ierr = PetscFree(points);CHKERRQ(ierr); 3076 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3077 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3078 /* Renumber points */ 3079 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3080 /* Sort points */ 3081 for (s = 0; s < newLabel->numStrata; ++s) { 3082 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3083 } 3084 /* Insert into list */ 3085 if (newNext) newNext->next = newLabel; 3086 else pmesh->labels = newLabel; 3087 newNext = newLabel; 3088 if (!rank) next = next->next; 3089 } 3090 } 3091 /* Cleanup Partition */ 3092 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3093 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3094 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3095 ierr = ISDestroy(&part);CHKERRQ(ierr); 3096 /* Create point SF for parallel mesh */ 3097 { 3098 const PetscInt *leaves; 3099 PetscSFNode *remotePoints, *rowners, *lowners; 3100 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3101 PetscInt pStart, pEnd; 3102 3103 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3104 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3105 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3106 for (p=0; p<numRoots; p++) { 3107 rowners[p].rank = -1; 3108 rowners[p].index = -1; 3109 } 3110 if (origCellPart) { 3111 /* Make sure cells in the original partition are not assigned to other procs */ 3112 const PetscInt *origCells; 3113 3114 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3115 for (p = 0; p < numProcs; ++p) { 3116 PetscInt dof, off, d; 3117 3118 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3119 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3120 for (d = off; d < off+dof; ++d) { 3121 rowners[origCells[d]].rank = p; 3122 } 3123 } 3124 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3125 } 3126 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3127 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3128 3129 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3130 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3131 for (p = 0; p < numLeaves; ++p) { 3132 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3133 lowners[p].rank = rank; 3134 lowners[p].index = leaves ? leaves[p] : p; 3135 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3136 lowners[p].rank = -2; 3137 lowners[p].index = -2; 3138 } 3139 } 3140 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3141 rowners[p].rank = -3; 3142 rowners[p].index = -3; 3143 } 3144 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3145 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3146 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3147 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3148 for (p = 0; p < numLeaves; ++p) { 3149 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3150 if (lowners[p].rank != rank) ++numGhostPoints; 3151 } 3152 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3153 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3154 for (p = 0, gp = 0; p < numLeaves; ++p) { 3155 if (lowners[p].rank != rank) { 3156 ghostPoints[gp] = leaves ? leaves[p] : p; 3157 remotePoints[gp].rank = lowners[p].rank; 3158 remotePoints[gp].index = lowners[p].index; 3159 ++gp; 3160 } 3161 } 3162 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3163 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3164 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3165 } 3166 /* Cleanup */ 3167 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3168 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3169 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3170 PetscFunctionReturn(0); 3171 } 3172 3173 #undef __FUNCT__ 3174 #define __FUNCT__ "DMPlexInvertCells_Internal" 3175 /* This is to fix the tetrahedron orientation from TetGen */ 3176 PETSC_UNUSED static PetscErrorCode DMPlexInvertCells_Internal(PetscInt numCells, PetscInt numCorners, int cells[]) 3177 { 3178 PetscInt c; 3179 3180 PetscFunctionBegin; 3181 if (numCorners != 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot invert cells with %d corners", numCorners); 3182 for (c = 0; c < numCells; ++c) { 3183 int *cone = &cells[c*4], tmpc; 3184 3185 tmpc = cone[0]; 3186 cone[0] = cone[1]; 3187 cone[1] = tmpc; 3188 } 3189 PetscFunctionReturn(0); 3190 } 3191 3192 #if defined(PETSC_HAVE_TRIANGLE) 3193 #include <triangle.h> 3194 3195 #undef __FUNCT__ 3196 #define __FUNCT__ "InitInput_Triangle" 3197 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 3198 { 3199 PetscFunctionBegin; 3200 inputCtx->numberofpoints = 0; 3201 inputCtx->numberofpointattributes = 0; 3202 inputCtx->pointlist = NULL; 3203 inputCtx->pointattributelist = NULL; 3204 inputCtx->pointmarkerlist = NULL; 3205 inputCtx->numberofsegments = 0; 3206 inputCtx->segmentlist = NULL; 3207 inputCtx->segmentmarkerlist = NULL; 3208 inputCtx->numberoftriangleattributes = 0; 3209 inputCtx->trianglelist = NULL; 3210 inputCtx->numberofholes = 0; 3211 inputCtx->holelist = NULL; 3212 inputCtx->numberofregions = 0; 3213 inputCtx->regionlist = NULL; 3214 PetscFunctionReturn(0); 3215 } 3216 3217 #undef __FUNCT__ 3218 #define __FUNCT__ "InitOutput_Triangle" 3219 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 3220 { 3221 PetscFunctionBegin; 3222 outputCtx->numberofpoints = 0; 3223 outputCtx->pointlist = NULL; 3224 outputCtx->pointattributelist = NULL; 3225 outputCtx->pointmarkerlist = NULL; 3226 outputCtx->numberoftriangles = 0; 3227 outputCtx->trianglelist = NULL; 3228 outputCtx->triangleattributelist = NULL; 3229 outputCtx->neighborlist = NULL; 3230 outputCtx->segmentlist = NULL; 3231 outputCtx->segmentmarkerlist = NULL; 3232 outputCtx->numberofedges = 0; 3233 outputCtx->edgelist = NULL; 3234 outputCtx->edgemarkerlist = NULL; 3235 PetscFunctionReturn(0); 3236 } 3237 3238 #undef __FUNCT__ 3239 #define __FUNCT__ "FiniOutput_Triangle" 3240 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 3241 { 3242 PetscFunctionBegin; 3243 free(outputCtx->pointmarkerlist); 3244 free(outputCtx->edgelist); 3245 free(outputCtx->edgemarkerlist); 3246 free(outputCtx->trianglelist); 3247 free(outputCtx->neighborlist); 3248 PetscFunctionReturn(0); 3249 } 3250 3251 #undef __FUNCT__ 3252 #define __FUNCT__ "DMPlexGenerate_Triangle" 3253 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 3254 { 3255 MPI_Comm comm; 3256 PetscInt dim = 2; 3257 const PetscBool createConvexHull = PETSC_FALSE; 3258 const PetscBool constrained = PETSC_FALSE; 3259 struct triangulateio in; 3260 struct triangulateio out; 3261 PetscInt vStart, vEnd, v, eStart, eEnd, e; 3262 PetscMPIInt rank; 3263 PetscErrorCode ierr; 3264 3265 PetscFunctionBegin; 3266 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3267 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3268 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 3269 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 3270 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3271 3272 in.numberofpoints = vEnd - vStart; 3273 if (in.numberofpoints > 0) { 3274 PetscSection coordSection; 3275 Vec coordinates; 3276 PetscScalar *array; 3277 3278 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 3279 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 3280 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3281 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3282 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3283 for (v = vStart; v < vEnd; ++v) { 3284 const PetscInt idx = v - vStart; 3285 PetscInt off, d; 3286 3287 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3288 for (d = 0; d < dim; ++d) { 3289 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3290 } 3291 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3292 } 3293 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3294 } 3295 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 3296 in.numberofsegments = eEnd - eStart; 3297 if (in.numberofsegments > 0) { 3298 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 3299 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 3300 for (e = eStart; e < eEnd; ++e) { 3301 const PetscInt idx = e - eStart; 3302 const PetscInt *cone; 3303 3304 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 3305 3306 in.segmentlist[idx*2+0] = cone[0] - vStart; 3307 in.segmentlist[idx*2+1] = cone[1] - vStart; 3308 3309 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 3310 } 3311 } 3312 #if 0 /* Do not currently support holes */ 3313 PetscReal *holeCoords; 3314 PetscInt h, d; 3315 3316 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 3317 if (in.numberofholes > 0) { 3318 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 3319 for (h = 0; h < in.numberofholes; ++h) { 3320 for (d = 0; d < dim; ++d) { 3321 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 3322 } 3323 } 3324 } 3325 #endif 3326 if (!rank) { 3327 char args[32]; 3328 3329 /* Take away 'Q' for verbose output */ 3330 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 3331 if (createConvexHull) { 3332 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 3333 } 3334 if (constrained) { 3335 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 3336 } 3337 triangulate(args, &in, &out, NULL); 3338 } 3339 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 3340 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 3341 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 3342 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 3343 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 3344 3345 { 3346 const PetscInt numCorners = 3; 3347 const PetscInt numCells = out.numberoftriangles; 3348 const PetscInt numVertices = out.numberofpoints; 3349 const int *cells = out.trianglelist; 3350 const double *meshCoords = out.pointlist; 3351 3352 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3353 /* Set labels */ 3354 for (v = 0; v < numVertices; ++v) { 3355 if (out.pointmarkerlist[v]) { 3356 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3357 } 3358 } 3359 if (interpolate) { 3360 for (e = 0; e < out.numberofedges; e++) { 3361 if (out.edgemarkerlist[e]) { 3362 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3363 const PetscInt *edges; 3364 PetscInt numEdges; 3365 3366 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3367 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3368 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3369 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3370 } 3371 } 3372 } 3373 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3374 } 3375 #if 0 /* Do not currently support holes */ 3376 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 3377 #endif 3378 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 3379 PetscFunctionReturn(0); 3380 } 3381 3382 #undef __FUNCT__ 3383 #define __FUNCT__ "DMPlexRefine_Triangle" 3384 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 3385 { 3386 MPI_Comm comm; 3387 PetscInt dim = 2; 3388 struct triangulateio in; 3389 struct triangulateio out; 3390 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3391 PetscMPIInt rank; 3392 PetscErrorCode ierr; 3393 3394 PetscFunctionBegin; 3395 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3396 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3397 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 3398 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 3399 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3400 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3401 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3402 3403 in.numberofpoints = vEnd - vStart; 3404 if (in.numberofpoints > 0) { 3405 PetscSection coordSection; 3406 Vec coordinates; 3407 PetscScalar *array; 3408 3409 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 3410 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 3411 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3412 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3413 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3414 for (v = vStart; v < vEnd; ++v) { 3415 const PetscInt idx = v - vStart; 3416 PetscInt off, d; 3417 3418 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3419 for (d = 0; d < dim; ++d) { 3420 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3421 } 3422 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3423 } 3424 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3425 } 3426 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3427 3428 in.numberofcorners = 3; 3429 in.numberoftriangles = cEnd - cStart; 3430 3431 in.trianglearealist = (double*) maxVolumes; 3432 if (in.numberoftriangles > 0) { 3433 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 3434 for (c = cStart; c < cEnd; ++c) { 3435 const PetscInt idx = c - cStart; 3436 PetscInt *closure = NULL; 3437 PetscInt closureSize; 3438 3439 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3440 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 3441 for (v = 0; v < 3; ++v) { 3442 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 3443 } 3444 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3445 } 3446 } 3447 /* TODO: Segment markers are missing on input */ 3448 #if 0 /* Do not currently support holes */ 3449 PetscReal *holeCoords; 3450 PetscInt h, d; 3451 3452 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 3453 if (in.numberofholes > 0) { 3454 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 3455 for (h = 0; h < in.numberofholes; ++h) { 3456 for (d = 0; d < dim; ++d) { 3457 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 3458 } 3459 } 3460 } 3461 #endif 3462 if (!rank) { 3463 char args[32]; 3464 3465 /* Take away 'Q' for verbose output */ 3466 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 3467 triangulate(args, &in, &out, NULL); 3468 } 3469 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 3470 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 3471 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 3472 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 3473 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 3474 3475 { 3476 const PetscInt numCorners = 3; 3477 const PetscInt numCells = out.numberoftriangles; 3478 const PetscInt numVertices = out.numberofpoints; 3479 const int *cells = out.trianglelist; 3480 const double *meshCoords = out.pointlist; 3481 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3482 3483 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3484 /* Set labels */ 3485 for (v = 0; v < numVertices; ++v) { 3486 if (out.pointmarkerlist[v]) { 3487 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3488 } 3489 } 3490 if (interpolate) { 3491 PetscInt e; 3492 3493 for (e = 0; e < out.numberofedges; e++) { 3494 if (out.edgemarkerlist[e]) { 3495 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3496 const PetscInt *edges; 3497 PetscInt numEdges; 3498 3499 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3500 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3501 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3502 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3503 } 3504 } 3505 } 3506 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3507 } 3508 #if 0 /* Do not currently support holes */ 3509 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 3510 #endif 3511 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 3512 PetscFunctionReturn(0); 3513 } 3514 #endif 3515 3516 #if defined(PETSC_HAVE_TETGEN) 3517 #include <tetgen.h> 3518 #undef __FUNCT__ 3519 #define __FUNCT__ "DMPlexGenerate_Tetgen" 3520 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 3521 { 3522 MPI_Comm comm; 3523 const PetscInt dim = 3; 3524 ::tetgenio in; 3525 ::tetgenio out; 3526 PetscInt vStart, vEnd, v, fStart, fEnd, f; 3527 PetscMPIInt rank; 3528 PetscErrorCode ierr; 3529 3530 PetscFunctionBegin; 3531 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3532 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3533 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3534 in.numberofpoints = vEnd - vStart; 3535 if (in.numberofpoints > 0) { 3536 PetscSection coordSection; 3537 Vec coordinates; 3538 PetscScalar *array; 3539 3540 in.pointlist = new double[in.numberofpoints*dim]; 3541 in.pointmarkerlist = new int[in.numberofpoints]; 3542 3543 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3544 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3545 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3546 for (v = vStart; v < vEnd; ++v) { 3547 const PetscInt idx = v - vStart; 3548 PetscInt off, d; 3549 3550 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3551 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 3552 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3553 } 3554 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3555 } 3556 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 3557 3558 in.numberoffacets = fEnd - fStart; 3559 if (in.numberoffacets > 0) { 3560 in.facetlist = new tetgenio::facet[in.numberoffacets]; 3561 in.facetmarkerlist = new int[in.numberoffacets]; 3562 for (f = fStart; f < fEnd; ++f) { 3563 const PetscInt idx = f - fStart; 3564 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 3565 3566 in.facetlist[idx].numberofpolygons = 1; 3567 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 3568 in.facetlist[idx].numberofholes = 0; 3569 in.facetlist[idx].holelist = NULL; 3570 3571 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3572 for (p = 0; p < numPoints*2; p += 2) { 3573 const PetscInt point = points[p]; 3574 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 3575 } 3576 3577 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 3578 poly->numberofvertices = numVertices; 3579 poly->vertexlist = new int[poly->numberofvertices]; 3580 for (v = 0; v < numVertices; ++v) { 3581 const PetscInt vIdx = points[v] - vStart; 3582 poly->vertexlist[v] = vIdx; 3583 } 3584 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 3585 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3586 } 3587 } 3588 if (!rank) { 3589 char args[32]; 3590 3591 /* Take away 'Q' for verbose output */ 3592 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 3593 ::tetrahedralize(args, &in, &out); 3594 } 3595 { 3596 const PetscInt numCorners = 4; 3597 const PetscInt numCells = out.numberoftetrahedra; 3598 const PetscInt numVertices = out.numberofpoints; 3599 const double *meshCoords = out.pointlist; 3600 int *cells = out.tetrahedronlist; 3601 3602 ierr = DMPlexInvertCells_Internal(numCells, numCorners, cells);CHKERRQ(ierr); 3603 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3604 /* Set labels */ 3605 for (v = 0; v < numVertices; ++v) { 3606 if (out.pointmarkerlist[v]) { 3607 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3608 } 3609 } 3610 if (interpolate) { 3611 PetscInt e; 3612 3613 for (e = 0; e < out.numberofedges; e++) { 3614 if (out.edgemarkerlist[e]) { 3615 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3616 const PetscInt *edges; 3617 PetscInt numEdges; 3618 3619 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3620 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3621 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3622 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3623 } 3624 } 3625 for (f = 0; f < out.numberoftrifaces; f++) { 3626 if (out.trifacemarkerlist[f]) { 3627 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 3628 const PetscInt *faces; 3629 PetscInt numFaces; 3630 3631 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3632 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3633 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 3634 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3635 } 3636 } 3637 } 3638 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3639 } 3640 PetscFunctionReturn(0); 3641 } 3642 3643 #undef __FUNCT__ 3644 #define __FUNCT__ "DMPlexRefine_Tetgen" 3645 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 3646 { 3647 MPI_Comm comm; 3648 const PetscInt dim = 3; 3649 ::tetgenio in; 3650 ::tetgenio out; 3651 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3652 PetscMPIInt rank; 3653 PetscErrorCode ierr; 3654 3655 PetscFunctionBegin; 3656 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3657 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3658 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3659 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3660 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3661 3662 in.numberofpoints = vEnd - vStart; 3663 if (in.numberofpoints > 0) { 3664 PetscSection coordSection; 3665 Vec coordinates; 3666 PetscScalar *array; 3667 3668 in.pointlist = new double[in.numberofpoints*dim]; 3669 in.pointmarkerlist = new int[in.numberofpoints]; 3670 3671 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3672 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3673 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3674 for (v = vStart; v < vEnd; ++v) { 3675 const PetscInt idx = v - vStart; 3676 PetscInt off, d; 3677 3678 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3679 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 3680 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3681 } 3682 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3683 } 3684 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3685 3686 in.numberofcorners = 4; 3687 in.numberoftetrahedra = cEnd - cStart; 3688 in.tetrahedronvolumelist = (double*) maxVolumes; 3689 if (in.numberoftetrahedra > 0) { 3690 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 3691 for (c = cStart; c < cEnd; ++c) { 3692 const PetscInt idx = c - cStart; 3693 PetscInt *closure = NULL; 3694 PetscInt closureSize; 3695 3696 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3697 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 3698 for (v = 0; v < 4; ++v) { 3699 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 3700 } 3701 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3702 } 3703 } 3704 /* TODO: Put in boundary faces with markers */ 3705 if (!rank) { 3706 char args[32]; 3707 3708 /* Take away 'Q' for verbose output */ 3709 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 3710 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 3711 ::tetrahedralize(args, &in, &out); 3712 } 3713 in.tetrahedronvolumelist = NULL; 3714 3715 { 3716 const PetscInt numCorners = 4; 3717 const PetscInt numCells = out.numberoftetrahedra; 3718 const PetscInt numVertices = out.numberofpoints; 3719 const double *meshCoords = out.pointlist; 3720 int *cells = out.tetrahedronlist; 3721 3722 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3723 3724 ierr = DMPlexInvertCells_Internal(numCells, numCorners, cells);CHKERRQ(ierr); 3725 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3726 /* Set labels */ 3727 for (v = 0; v < numVertices; ++v) { 3728 if (out.pointmarkerlist[v]) { 3729 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3730 } 3731 } 3732 if (interpolate) { 3733 PetscInt e, f; 3734 3735 for (e = 0; e < out.numberofedges; e++) { 3736 if (out.edgemarkerlist[e]) { 3737 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3738 const PetscInt *edges; 3739 PetscInt numEdges; 3740 3741 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3742 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3743 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3744 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3745 } 3746 } 3747 for (f = 0; f < out.numberoftrifaces; f++) { 3748 if (out.trifacemarkerlist[f]) { 3749 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 3750 const PetscInt *faces; 3751 PetscInt numFaces; 3752 3753 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3754 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3755 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 3756 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3757 } 3758 } 3759 } 3760 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3761 } 3762 PetscFunctionReturn(0); 3763 } 3764 #endif 3765 3766 #if defined(PETSC_HAVE_CTETGEN) 3767 #include "ctetgen.h" 3768 3769 #undef __FUNCT__ 3770 #define __FUNCT__ "DMPlexGenerate_CTetgen" 3771 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 3772 { 3773 MPI_Comm comm; 3774 const PetscInt dim = 3; 3775 PLC *in, *out; 3776 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 3777 PetscMPIInt rank; 3778 PetscErrorCode ierr; 3779 3780 PetscFunctionBegin; 3781 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3782 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3783 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3784 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3785 ierr = PLCCreate(&in);CHKERRQ(ierr); 3786 ierr = PLCCreate(&out);CHKERRQ(ierr); 3787 3788 in->numberofpoints = vEnd - vStart; 3789 if (in->numberofpoints > 0) { 3790 PetscSection coordSection; 3791 Vec coordinates; 3792 PetscScalar *array; 3793 3794 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 3795 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 3796 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3797 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3798 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3799 for (v = vStart; v < vEnd; ++v) { 3800 const PetscInt idx = v - vStart; 3801 PetscInt off, d, m; 3802 3803 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3804 for (d = 0; d < dim; ++d) { 3805 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3806 } 3807 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 3808 3809 in->pointmarkerlist[idx] = (int) m; 3810 } 3811 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3812 } 3813 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 3814 3815 in->numberoffacets = fEnd - fStart; 3816 if (in->numberoffacets > 0) { 3817 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 3818 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 3819 for (f = fStart; f < fEnd; ++f) { 3820 const PetscInt idx = f - fStart; 3821 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 3822 polygon *poly; 3823 3824 in->facetlist[idx].numberofpolygons = 1; 3825 3826 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 3827 3828 in->facetlist[idx].numberofholes = 0; 3829 in->facetlist[idx].holelist = NULL; 3830 3831 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3832 for (p = 0; p < numPoints*2; p += 2) { 3833 const PetscInt point = points[p]; 3834 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 3835 } 3836 3837 poly = in->facetlist[idx].polygonlist; 3838 poly->numberofvertices = numVertices; 3839 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 3840 for (v = 0; v < numVertices; ++v) { 3841 const PetscInt vIdx = points[v] - vStart; 3842 poly->vertexlist[v] = vIdx; 3843 } 3844 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 3845 in->facetmarkerlist[idx] = (int) m; 3846 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3847 } 3848 } 3849 if (!rank) { 3850 TetGenOpts t; 3851 3852 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3853 t.in = boundary; /* Should go away */ 3854 t.plc = 1; 3855 t.quality = 1; 3856 t.edgesout = 1; 3857 t.zeroindex = 1; 3858 t.quiet = 1; 3859 t.verbose = verbose; 3860 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3861 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3862 } 3863 { 3864 const PetscInt numCorners = 4; 3865 const PetscInt numCells = out->numberoftetrahedra; 3866 const PetscInt numVertices = out->numberofpoints; 3867 const double *meshCoords = out->pointlist; 3868 int *cells = out->tetrahedronlist; 3869 3870 ierr = DMPlexInvertCells_Internal(numCells, numCorners, cells);CHKERRQ(ierr); 3871 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3872 /* Set labels */ 3873 for (v = 0; v < numVertices; ++v) { 3874 if (out->pointmarkerlist[v]) { 3875 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 3876 } 3877 } 3878 if (interpolate) { 3879 PetscInt e; 3880 3881 for (e = 0; e < out->numberofedges; e++) { 3882 if (out->edgemarkerlist[e]) { 3883 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 3884 const PetscInt *edges; 3885 PetscInt numEdges; 3886 3887 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3888 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3889 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 3890 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3891 } 3892 } 3893 for (f = 0; f < out->numberoftrifaces; f++) { 3894 if (out->trifacemarkerlist[f]) { 3895 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 3896 const PetscInt *faces; 3897 PetscInt numFaces; 3898 3899 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3900 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3901 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 3902 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3903 } 3904 } 3905 } 3906 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3907 } 3908 3909 ierr = PLCDestroy(&in);CHKERRQ(ierr); 3910 ierr = PLCDestroy(&out);CHKERRQ(ierr); 3911 PetscFunctionReturn(0); 3912 } 3913 3914 #undef __FUNCT__ 3915 #define __FUNCT__ "DMPlexRefine_CTetgen" 3916 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 3917 { 3918 MPI_Comm comm; 3919 const PetscInt dim = 3; 3920 PLC *in, *out; 3921 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3922 PetscMPIInt rank; 3923 PetscErrorCode ierr; 3924 3925 PetscFunctionBegin; 3926 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3927 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3928 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3929 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3930 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3931 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3932 ierr = PLCCreate(&in);CHKERRQ(ierr); 3933 ierr = PLCCreate(&out);CHKERRQ(ierr); 3934 3935 in->numberofpoints = vEnd - vStart; 3936 if (in->numberofpoints > 0) { 3937 PetscSection coordSection; 3938 Vec coordinates; 3939 PetscScalar *array; 3940 3941 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 3942 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 3943 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3944 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3945 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3946 for (v = vStart; v < vEnd; ++v) { 3947 const PetscInt idx = v - vStart; 3948 PetscInt off, d, m; 3949 3950 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3951 for (d = 0; d < dim; ++d) { 3952 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3953 } 3954 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 3955 3956 in->pointmarkerlist[idx] = (int) m; 3957 } 3958 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3959 } 3960 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3961 3962 in->numberofcorners = 4; 3963 in->numberoftetrahedra = cEnd - cStart; 3964 in->tetrahedronvolumelist = maxVolumes; 3965 if (in->numberoftetrahedra > 0) { 3966 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 3967 for (c = cStart; c < cEnd; ++c) { 3968 const PetscInt idx = c - cStart; 3969 PetscInt *closure = NULL; 3970 PetscInt closureSize; 3971 3972 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3973 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 3974 for (v = 0; v < 4; ++v) { 3975 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 3976 } 3977 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3978 } 3979 } 3980 if (!rank) { 3981 TetGenOpts t; 3982 3983 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3984 3985 t.in = dm; /* Should go away */ 3986 t.refine = 1; 3987 t.varvolume = 1; 3988 t.quality = 1; 3989 t.edgesout = 1; 3990 t.zeroindex = 1; 3991 t.quiet = 1; 3992 t.verbose = verbose; /* Change this */ 3993 3994 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3995 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3996 } 3997 { 3998 const PetscInt numCorners = 4; 3999 const PetscInt numCells = out->numberoftetrahedra; 4000 const PetscInt numVertices = out->numberofpoints; 4001 const double *meshCoords = out->pointlist; 4002 int *cells = out->tetrahedronlist; 4003 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4004 4005 ierr = DMPlexInvertCells_Internal(numCells, numCorners, cells);CHKERRQ(ierr); 4006 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 4007 /* Set labels */ 4008 for (v = 0; v < numVertices; ++v) { 4009 if (out->pointmarkerlist[v]) { 4010 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 4011 } 4012 } 4013 if (interpolate) { 4014 PetscInt e, f; 4015 4016 for (e = 0; e < out->numberofedges; e++) { 4017 if (out->edgemarkerlist[e]) { 4018 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 4019 const PetscInt *edges; 4020 PetscInt numEdges; 4021 4022 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4023 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4024 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 4025 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4026 } 4027 } 4028 for (f = 0; f < out->numberoftrifaces; f++) { 4029 if (out->trifacemarkerlist[f]) { 4030 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 4031 const PetscInt *faces; 4032 PetscInt numFaces; 4033 4034 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4035 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4036 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 4037 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4038 } 4039 } 4040 } 4041 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4042 } 4043 ierr = PLCDestroy(&in);CHKERRQ(ierr); 4044 ierr = PLCDestroy(&out);CHKERRQ(ierr); 4045 PetscFunctionReturn(0); 4046 } 4047 #endif 4048 4049 #undef __FUNCT__ 4050 #define __FUNCT__ "DMPlexGenerate" 4051 /*@C 4052 DMPlexGenerate - Generates a mesh. 4053 4054 Not Collective 4055 4056 Input Parameters: 4057 + boundary - The DMPlex boundary object 4058 . name - The mesh generation package name 4059 - interpolate - Flag to create intermediate mesh elements 4060 4061 Output Parameter: 4062 . mesh - The DMPlex object 4063 4064 Level: intermediate 4065 4066 .keywords: mesh, elements 4067 .seealso: DMPlexCreate(), DMRefine() 4068 @*/ 4069 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 4070 { 4071 PetscInt dim; 4072 char genname[1024]; 4073 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 4074 PetscErrorCode ierr; 4075 4076 PetscFunctionBegin; 4077 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 4078 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 4079 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 4080 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 4081 if (flg) name = genname; 4082 if (name) { 4083 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 4084 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 4085 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 4086 } 4087 switch (dim) { 4088 case 1: 4089 if (!name || isTriangle) { 4090 #if defined(PETSC_HAVE_TRIANGLE) 4091 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 4092 #else 4093 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 4094 #endif 4095 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 4096 break; 4097 case 2: 4098 if (!name || isCTetgen) { 4099 #if defined(PETSC_HAVE_CTETGEN) 4100 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 4101 #else 4102 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 4103 #endif 4104 } else if (isTetgen) { 4105 #if defined(PETSC_HAVE_TETGEN) 4106 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 4107 #else 4108 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 4109 #endif 4110 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 4111 break; 4112 default: 4113 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 4114 } 4115 PetscFunctionReturn(0); 4116 } 4117 4118 typedef PetscInt CellRefiner; 4119 4120 #undef __FUNCT__ 4121 #define __FUNCT__ "GetDepthStart_Private" 4122 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 4123 { 4124 PetscFunctionBegin; 4125 if (cStart) *cStart = 0; 4126 if (vStart) *vStart = depthSize[depth]; 4127 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 4128 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 4129 PetscFunctionReturn(0); 4130 } 4131 4132 #undef __FUNCT__ 4133 #define __FUNCT__ "GetDepthEnd_Private" 4134 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 4135 { 4136 PetscFunctionBegin; 4137 if (cEnd) *cEnd = depthSize[depth]; 4138 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 4139 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 4140 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 4141 PetscFunctionReturn(0); 4142 } 4143 4144 #undef __FUNCT__ 4145 #define __FUNCT__ "CellRefinerGetSizes" 4146 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 4147 { 4148 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 4149 PetscErrorCode ierr; 4150 4151 PetscFunctionBegin; 4152 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4153 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4154 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4155 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4156 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4157 switch (refiner) { 4158 case 1: 4159 /* Simplicial 2D */ 4160 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 4161 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 4162 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 4163 break; 4164 case 3: 4165 /* Hybrid 2D */ 4166 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4167 cMax = PetscMin(cEnd, cMax); 4168 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4169 fMax = PetscMin(fEnd, fMax); 4170 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 4171 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 */ 4172 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 4173 break; 4174 case 2: 4175 /* Hex 2D */ 4176 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 4177 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 4178 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 4179 break; 4180 default: 4181 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 4182 } 4183 PetscFunctionReturn(0); 4184 } 4185 4186 #undef __FUNCT__ 4187 #define __FUNCT__ "CellRefinerSetConeSizes" 4188 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 4189 { 4190 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 4191 PetscErrorCode ierr; 4192 4193 PetscFunctionBegin; 4194 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4195 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4196 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4197 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4198 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4199 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4200 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 4201 switch (refiner) { 4202 case 1: 4203 /* Simplicial 2D */ 4204 /* All cells have 3 faces */ 4205 for (c = cStart; c < cEnd; ++c) { 4206 for (r = 0; r < 4; ++r) { 4207 const PetscInt newp = (c - cStart)*4 + r; 4208 4209 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 4210 } 4211 } 4212 /* Split faces have 2 vertices and the same cells as the parent */ 4213 for (f = fStart; f < fEnd; ++f) { 4214 for (r = 0; r < 2; ++r) { 4215 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4216 PetscInt size; 4217 4218 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4219 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4220 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4221 } 4222 } 4223 /* Interior faces have 2 vertices and 2 cells */ 4224 for (c = cStart; c < cEnd; ++c) { 4225 for (r = 0; r < 3; ++r) { 4226 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 4227 4228 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4229 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4230 } 4231 } 4232 /* Old vertices have identical supports */ 4233 for (v = vStart; v < vEnd; ++v) { 4234 const PetscInt newp = vStartNew + (v - vStart); 4235 PetscInt size; 4236 4237 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4238 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4239 } 4240 /* Face vertices have 2 + cells*2 supports */ 4241 for (f = fStart; f < fEnd; ++f) { 4242 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4243 PetscInt size; 4244 4245 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4246 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 4247 } 4248 break; 4249 case 2: 4250 /* Hex 2D */ 4251 /* All cells have 4 faces */ 4252 for (c = cStart; c < cEnd; ++c) { 4253 for (r = 0; r < 4; ++r) { 4254 const PetscInt newp = (c - cStart)*4 + r; 4255 4256 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 4257 } 4258 } 4259 /* Split faces have 2 vertices and the same cells as the parent */ 4260 for (f = fStart; f < fEnd; ++f) { 4261 for (r = 0; r < 2; ++r) { 4262 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4263 PetscInt size; 4264 4265 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4266 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4267 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4268 } 4269 } 4270 /* Interior faces have 2 vertices and 2 cells */ 4271 for (c = cStart; c < cEnd; ++c) { 4272 for (r = 0; r < 4; ++r) { 4273 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4274 4275 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4276 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4277 } 4278 } 4279 /* Old vertices have identical supports */ 4280 for (v = vStart; v < vEnd; ++v) { 4281 const PetscInt newp = vStartNew + (v - vStart); 4282 PetscInt size; 4283 4284 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4285 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4286 } 4287 /* Face vertices have 2 + cells supports */ 4288 for (f = fStart; f < fEnd; ++f) { 4289 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4290 PetscInt size; 4291 4292 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4293 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 4294 } 4295 /* Cell vertices have 4 supports */ 4296 for (c = cStart; c < cEnd; ++c) { 4297 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4298 4299 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 4300 } 4301 break; 4302 case 3: 4303 /* Hybrid 2D */ 4304 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4305 cMax = PetscMin(cEnd, cMax); 4306 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4307 fMax = PetscMin(fEnd, fMax); 4308 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 4309 /* Interior cells have 3 faces */ 4310 for (c = cStart; c < cMax; ++c) { 4311 for (r = 0; r < 4; ++r) { 4312 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 4313 4314 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 4315 } 4316 } 4317 /* Hybrid cells have 4 faces */ 4318 for (c = cMax; c < cEnd; ++c) { 4319 for (r = 0; r < 2; ++r) { 4320 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 4321 4322 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 4323 } 4324 } 4325 /* Interior split faces have 2 vertices and the same cells as the parent */ 4326 for (f = fStart; f < fMax; ++f) { 4327 for (r = 0; r < 2; ++r) { 4328 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4329 PetscInt size; 4330 4331 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4332 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4333 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4334 } 4335 } 4336 /* Interior cell faces have 2 vertices and 2 cells */ 4337 for (c = cStart; c < cMax; ++c) { 4338 for (r = 0; r < 3; ++r) { 4339 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 4340 4341 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4342 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4343 } 4344 } 4345 /* Hybrid faces have 2 vertices and the same cells */ 4346 for (f = fMax; f < fEnd; ++f) { 4347 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 4348 PetscInt size; 4349 4350 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4351 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4352 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4353 } 4354 /* Hybrid cell faces have 2 vertices and 2 cells */ 4355 for (c = cMax; c < cEnd; ++c) { 4356 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4357 4358 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4359 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4360 } 4361 /* Old vertices have identical supports */ 4362 for (v = vStart; v < vEnd; ++v) { 4363 const PetscInt newp = vStartNew + (v - vStart); 4364 PetscInt size; 4365 4366 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4367 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4368 } 4369 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 4370 for (f = fStart; f < fMax; ++f) { 4371 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4372 const PetscInt *support; 4373 PetscInt size, newSize = 2, s; 4374 4375 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4376 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4377 for (s = 0; s < size; ++s) { 4378 if (support[s] >= cMax) newSize += 1; 4379 else newSize += 2; 4380 } 4381 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 4382 } 4383 break; 4384 default: 4385 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 4386 } 4387 PetscFunctionReturn(0); 4388 } 4389 4390 #undef __FUNCT__ 4391 #define __FUNCT__ "CellRefinerSetCones" 4392 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 4393 { 4394 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; 4395 PetscInt maxSupportSize, *supportRef; 4396 PetscErrorCode ierr; 4397 4398 PetscFunctionBegin; 4399 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4400 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4401 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4402 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4403 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4404 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4405 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 4406 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 4407 switch (refiner) { 4408 case 1: 4409 /* Simplicial 2D */ 4410 /* 4411 2 4412 |\ 4413 | \ 4414 | \ 4415 | \ 4416 | C \ 4417 | \ 4418 | \ 4419 2---1---1 4420 |\ D / \ 4421 | 2 0 \ 4422 |A \ / B \ 4423 0---0-------1 4424 */ 4425 /* All cells have 3 faces */ 4426 for (c = cStart; c < cEnd; ++c) { 4427 const PetscInt newp = cStartNew + (c - cStart)*4; 4428 const PetscInt *cone, *ornt; 4429 PetscInt coneNew[3], orntNew[3]; 4430 4431 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4432 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4433 /* A triangle */ 4434 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4435 orntNew[0] = ornt[0]; 4436 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 4437 orntNew[1] = -2; 4438 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4439 orntNew[2] = ornt[2]; 4440 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4441 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4442 #if 1 4443 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); 4444 for (p = 0; p < 3; ++p) { 4445 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); 4446 } 4447 #endif 4448 /* B triangle */ 4449 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4450 orntNew[0] = ornt[0]; 4451 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4452 orntNew[1] = ornt[1]; 4453 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 4454 orntNew[2] = -2; 4455 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4456 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4457 #if 1 4458 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); 4459 for (p = 0; p < 3; ++p) { 4460 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); 4461 } 4462 #endif 4463 /* C triangle */ 4464 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 4465 orntNew[0] = -2; 4466 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4467 orntNew[1] = ornt[1]; 4468 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4469 orntNew[2] = ornt[2]; 4470 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4471 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4472 #if 1 4473 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); 4474 for (p = 0; p < 3; ++p) { 4475 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); 4476 } 4477 #endif 4478 /* D triangle */ 4479 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 4480 orntNew[0] = 0; 4481 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 4482 orntNew[1] = 0; 4483 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 4484 orntNew[2] = 0; 4485 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4486 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4487 #if 1 4488 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); 4489 for (p = 0; p < 3; ++p) { 4490 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); 4491 } 4492 #endif 4493 } 4494 /* Split faces have 2 vertices and the same cells as the parent */ 4495 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4496 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4497 for (f = fStart; f < fEnd; ++f) { 4498 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4499 4500 for (r = 0; r < 2; ++r) { 4501 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4502 const PetscInt *cone, *support; 4503 PetscInt coneNew[2], coneSize, c, supportSize, s; 4504 4505 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4506 coneNew[0] = vStartNew + (cone[0] - vStart); 4507 coneNew[1] = vStartNew + (cone[1] - vStart); 4508 coneNew[(r+1)%2] = newv; 4509 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4510 #if 1 4511 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4512 for (p = 0; p < 2; ++p) { 4513 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); 4514 } 4515 #endif 4516 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4517 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4518 for (s = 0; s < supportSize; ++s) { 4519 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4520 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4521 for (c = 0; c < coneSize; ++c) { 4522 if (cone[c] == f) break; 4523 } 4524 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 4525 } 4526 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4527 #if 1 4528 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4529 for (p = 0; p < supportSize; ++p) { 4530 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); 4531 } 4532 #endif 4533 } 4534 } 4535 /* Interior faces have 2 vertices and 2 cells */ 4536 for (c = cStart; c < cEnd; ++c) { 4537 const PetscInt *cone; 4538 4539 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4540 for (r = 0; r < 3; ++r) { 4541 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 4542 PetscInt coneNew[2]; 4543 PetscInt supportNew[2]; 4544 4545 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4546 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 4547 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4548 #if 1 4549 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4550 for (p = 0; p < 2; ++p) { 4551 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); 4552 } 4553 #endif 4554 supportNew[0] = (c - cStart)*4 + (r+1)%3; 4555 supportNew[1] = (c - cStart)*4 + 3; 4556 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4557 #if 1 4558 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4559 for (p = 0; p < 2; ++p) { 4560 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); 4561 } 4562 #endif 4563 } 4564 } 4565 /* Old vertices have identical supports */ 4566 for (v = vStart; v < vEnd; ++v) { 4567 const PetscInt newp = vStartNew + (v - vStart); 4568 const PetscInt *support, *cone; 4569 PetscInt size, s; 4570 4571 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4572 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 4573 for (s = 0; s < size; ++s) { 4574 PetscInt r = 0; 4575 4576 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4577 if (cone[1] == v) r = 1; 4578 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 4579 } 4580 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4581 #if 1 4582 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4583 for (p = 0; p < size; ++p) { 4584 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); 4585 } 4586 #endif 4587 } 4588 /* Face vertices have 2 + cells*2 supports */ 4589 for (f = fStart; f < fEnd; ++f) { 4590 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4591 const PetscInt *cone, *support; 4592 PetscInt size, s; 4593 4594 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4595 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4596 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 4597 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 4598 for (s = 0; s < size; ++s) { 4599 PetscInt r = 0; 4600 4601 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4602 if (cone[1] == f) r = 1; 4603 else if (cone[2] == f) r = 2; 4604 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 4605 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 4606 } 4607 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4608 #if 1 4609 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4610 for (p = 0; p < 2+size*2; ++p) { 4611 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); 4612 } 4613 #endif 4614 } 4615 ierr = PetscFree(supportRef);CHKERRQ(ierr); 4616 break; 4617 case 2: 4618 /* Hex 2D */ 4619 /* 4620 3---------2---------2 4621 | | | 4622 | D 2 C | 4623 | | | 4624 3----3----0----1----1 4625 | | | 4626 | A 0 B | 4627 | | | 4628 0---------0---------1 4629 */ 4630 /* All cells have 4 faces */ 4631 for (c = cStart; c < cEnd; ++c) { 4632 const PetscInt newp = (c - cStart)*4; 4633 const PetscInt *cone, *ornt; 4634 PetscInt coneNew[4], orntNew[4]; 4635 4636 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4637 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4638 /* A quad */ 4639 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4640 orntNew[0] = ornt[0]; 4641 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 4642 orntNew[1] = 0; 4643 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 4644 orntNew[2] = -2; 4645 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 4646 orntNew[3] = ornt[3]; 4647 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4648 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4649 #if 1 4650 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); 4651 for (p = 0; p < 4; ++p) { 4652 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); 4653 } 4654 #endif 4655 /* B quad */ 4656 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4657 orntNew[0] = ornt[0]; 4658 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4659 orntNew[1] = ornt[1]; 4660 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 4661 orntNew[2] = 0; 4662 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 4663 orntNew[3] = -2; 4664 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4665 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4666 #if 1 4667 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); 4668 for (p = 0; p < 4; ++p) { 4669 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); 4670 } 4671 #endif 4672 /* C quad */ 4673 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 4674 orntNew[0] = -2; 4675 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4676 orntNew[1] = ornt[1]; 4677 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4678 orntNew[2] = ornt[2]; 4679 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 4680 orntNew[3] = 0; 4681 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4682 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4683 #if 1 4684 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); 4685 for (p = 0; p < 4; ++p) { 4686 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); 4687 } 4688 #endif 4689 /* D quad */ 4690 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 4691 orntNew[0] = 0; 4692 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 4693 orntNew[1] = -2; 4694 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4695 orntNew[2] = ornt[2]; 4696 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 4697 orntNew[3] = ornt[3]; 4698 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4699 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4700 #if 1 4701 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); 4702 for (p = 0; p < 4; ++p) { 4703 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); 4704 } 4705 #endif 4706 } 4707 /* Split faces have 2 vertices and the same cells as the parent */ 4708 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4709 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4710 for (f = fStart; f < fEnd; ++f) { 4711 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4712 4713 for (r = 0; r < 2; ++r) { 4714 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4715 const PetscInt *cone, *support; 4716 PetscInt coneNew[2], coneSize, c, supportSize, s; 4717 4718 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4719 coneNew[0] = vStartNew + (cone[0] - vStart); 4720 coneNew[1] = vStartNew + (cone[1] - vStart); 4721 coneNew[(r+1)%2] = newv; 4722 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4723 #if 1 4724 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4725 for (p = 0; p < 2; ++p) { 4726 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); 4727 } 4728 #endif 4729 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4730 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4731 for (s = 0; s < supportSize; ++s) { 4732 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4733 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4734 for (c = 0; c < coneSize; ++c) { 4735 if (cone[c] == f) break; 4736 } 4737 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 4738 } 4739 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4740 #if 1 4741 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4742 for (p = 0; p < supportSize; ++p) { 4743 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); 4744 } 4745 #endif 4746 } 4747 } 4748 /* Interior faces have 2 vertices and 2 cells */ 4749 for (c = cStart; c < cEnd; ++c) { 4750 const PetscInt *cone; 4751 PetscInt coneNew[2], supportNew[2]; 4752 4753 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4754 for (r = 0; r < 4; ++r) { 4755 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4756 4757 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4758 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4759 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4760 #if 1 4761 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4762 for (p = 0; p < 2; ++p) { 4763 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); 4764 } 4765 #endif 4766 supportNew[0] = (c - cStart)*4 + r; 4767 supportNew[1] = (c - cStart)*4 + (r+1)%4; 4768 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4769 #if 1 4770 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4771 for (p = 0; p < 2; ++p) { 4772 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); 4773 } 4774 #endif 4775 } 4776 } 4777 /* Old vertices have identical supports */ 4778 for (v = vStart; v < vEnd; ++v) { 4779 const PetscInt newp = vStartNew + (v - vStart); 4780 const PetscInt *support, *cone; 4781 PetscInt size, s; 4782 4783 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4784 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 4785 for (s = 0; s < size; ++s) { 4786 PetscInt r = 0; 4787 4788 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4789 if (cone[1] == v) r = 1; 4790 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 4791 } 4792 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4793 #if 1 4794 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4795 for (p = 0; p < size; ++p) { 4796 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); 4797 } 4798 #endif 4799 } 4800 /* Face vertices have 2 + cells supports */ 4801 for (f = fStart; f < fEnd; ++f) { 4802 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4803 const PetscInt *cone, *support; 4804 PetscInt size, s; 4805 4806 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4807 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4808 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 4809 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 4810 for (s = 0; s < size; ++s) { 4811 PetscInt r = 0; 4812 4813 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4814 if (cone[1] == f) r = 1; 4815 else if (cone[2] == f) r = 2; 4816 else if (cone[3] == f) r = 3; 4817 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 4818 } 4819 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4820 #if 1 4821 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4822 for (p = 0; p < 2+size; ++p) { 4823 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); 4824 } 4825 #endif 4826 } 4827 /* Cell vertices have 4 supports */ 4828 for (c = cStart; c < cEnd; ++c) { 4829 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4830 PetscInt supportNew[4]; 4831 4832 for (r = 0; r < 4; ++r) { 4833 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4834 } 4835 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4836 } 4837 break; 4838 case 3: 4839 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4840 cMax = PetscMin(cEnd, cMax); 4841 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4842 fMax = PetscMin(fEnd, fMax); 4843 /* Interior cells have 3 faces */ 4844 for (c = cStart; c < cMax; ++c) { 4845 const PetscInt newp = cStartNew + (c - cStart)*4; 4846 const PetscInt *cone, *ornt; 4847 PetscInt coneNew[3], orntNew[3]; 4848 4849 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4850 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4851 /* A triangle */ 4852 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4853 orntNew[0] = ornt[0]; 4854 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 4855 orntNew[1] = -2; 4856 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4857 orntNew[2] = ornt[2]; 4858 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4859 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4860 #if 1 4861 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); 4862 for (p = 0; p < 3; ++p) { 4863 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); 4864 } 4865 #endif 4866 /* B triangle */ 4867 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4868 orntNew[0] = ornt[0]; 4869 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4870 orntNew[1] = ornt[1]; 4871 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 4872 orntNew[2] = -2; 4873 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4874 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4875 #if 1 4876 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); 4877 for (p = 0; p < 3; ++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 /* C triangle */ 4882 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 4883 orntNew[0] = -2; 4884 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4885 orntNew[1] = ornt[1]; 4886 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4887 orntNew[2] = ornt[2]; 4888 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4889 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4890 #if 1 4891 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); 4892 for (p = 0; p < 3; ++p) { 4893 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); 4894 } 4895 #endif 4896 /* D triangle */ 4897 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 4898 orntNew[0] = 0; 4899 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 4900 orntNew[1] = 0; 4901 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 4902 orntNew[2] = 0; 4903 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4904 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4905 #if 1 4906 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); 4907 for (p = 0; p < 3; ++p) { 4908 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); 4909 } 4910 #endif 4911 } 4912 /* 4913 2----3----3 4914 | | 4915 | B | 4916 | | 4917 0----4--- 1 4918 | | 4919 | A | 4920 | | 4921 0----2----1 4922 */ 4923 /* Hybrid cells have 4 faces */ 4924 for (c = cMax; c < cEnd; ++c) { 4925 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 4926 const PetscInt *cone, *ornt; 4927 PetscInt coneNew[4], orntNew[4]; 4928 4929 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4930 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4931 /* A quad */ 4932 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4933 orntNew[0] = ornt[0]; 4934 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4935 orntNew[1] = ornt[1]; 4936 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 4937 orntNew[2] = 0; 4938 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4939 orntNew[3] = 0; 4940 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4941 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4942 #if 1 4943 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); 4944 for (p = 0; p < 4; ++p) { 4945 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); 4946 } 4947 #endif 4948 /* B quad */ 4949 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4950 orntNew[0] = ornt[0]; 4951 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4952 orntNew[1] = ornt[1]; 4953 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4954 orntNew[2] = 0; 4955 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 4956 orntNew[3] = 0; 4957 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4958 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4959 #if 1 4960 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); 4961 for (p = 0; p < 4; ++p) { 4962 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); 4963 } 4964 #endif 4965 } 4966 /* Interior split faces have 2 vertices and the same cells as the parent */ 4967 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4968 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4969 for (f = fStart; f < fMax; ++f) { 4970 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4971 4972 for (r = 0; r < 2; ++r) { 4973 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4974 const PetscInt *cone, *support; 4975 PetscInt coneNew[2], coneSize, c, supportSize, s; 4976 4977 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4978 coneNew[0] = vStartNew + (cone[0] - vStart); 4979 coneNew[1] = vStartNew + (cone[1] - vStart); 4980 coneNew[(r+1)%2] = newv; 4981 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4982 #if 1 4983 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4984 for (p = 0; p < 2; ++p) { 4985 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 4986 } 4987 #endif 4988 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4989 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4990 for (s = 0; s < supportSize; ++s) { 4991 if (support[s] >= cMax) { 4992 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 4993 } else { 4994 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4995 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4996 for (c = 0; c < coneSize; ++c) { 4997 if (cone[c] == f) break; 4998 } 4999 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5000 } 5001 } 5002 ierr = DMPlexSetSupport(rdm, newp, supportRef);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 < supportSize; ++p) { 5006 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); 5007 } 5008 #endif 5009 } 5010 } 5011 /* Interior cell faces have 2 vertices and 2 cells */ 5012 for (c = cStart; c < cMax; ++c) { 5013 const PetscInt *cone; 5014 5015 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5016 for (r = 0; r < 3; ++r) { 5017 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5018 PetscInt coneNew[2]; 5019 PetscInt supportNew[2]; 5020 5021 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5022 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5023 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5024 #if 1 5025 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5026 for (p = 0; p < 2; ++p) { 5027 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); 5028 } 5029 #endif 5030 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5031 supportNew[1] = (c - cStart)*4 + 3; 5032 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5033 #if 1 5034 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5035 for (p = 0; p < 2; ++p) { 5036 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); 5037 } 5038 #endif 5039 } 5040 } 5041 /* Interior hybrid faces have 2 vertices and the same cells */ 5042 for (f = fMax; f < fEnd; ++f) { 5043 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5044 const PetscInt *cone; 5045 const PetscInt *support; 5046 PetscInt coneNew[2]; 5047 PetscInt supportNew[2]; 5048 PetscInt size, s, r; 5049 5050 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5051 coneNew[0] = vStartNew + (cone[0] - vStart); 5052 coneNew[1] = vStartNew + (cone[1] - vStart); 5053 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5054 #if 1 5055 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5056 for (p = 0; p < 2; ++p) { 5057 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); 5058 } 5059 #endif 5060 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5061 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5062 for (s = 0; s < size; ++s) { 5063 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5064 for (r = 0; r < 2; ++r) { 5065 if (cone[r+2] == f) break; 5066 } 5067 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 5068 } 5069 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5070 #if 1 5071 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5072 for (p = 0; p < size; ++p) { 5073 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); 5074 } 5075 #endif 5076 } 5077 /* Cell hybrid faces have 2 vertices and 2 cells */ 5078 for (c = cMax; c < cEnd; ++c) { 5079 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5080 const PetscInt *cone; 5081 PetscInt coneNew[2]; 5082 PetscInt supportNew[2]; 5083 5084 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5085 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 5086 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 5087 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5088 #if 1 5089 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5090 for (p = 0; p < 2; ++p) { 5091 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); 5092 } 5093 #endif 5094 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 5095 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 5096 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5097 #if 1 5098 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5099 for (p = 0; p < 2; ++p) { 5100 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); 5101 } 5102 #endif 5103 } 5104 /* Old vertices have identical supports */ 5105 for (v = vStart; v < vEnd; ++v) { 5106 const PetscInt newp = vStartNew + (v - vStart); 5107 const PetscInt *support, *cone; 5108 PetscInt size, s; 5109 5110 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5111 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5112 for (s = 0; s < size; ++s) { 5113 if (support[s] >= fMax) { 5114 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 5115 } else { 5116 PetscInt r = 0; 5117 5118 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5119 if (cone[1] == v) r = 1; 5120 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5121 } 5122 } 5123 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5124 #if 1 5125 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5126 for (p = 0; p < size; ++p) { 5127 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); 5128 } 5129 #endif 5130 } 5131 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5132 for (f = fStart; f < fMax; ++f) { 5133 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5134 const PetscInt *cone, *support; 5135 PetscInt size, newSize = 2, s; 5136 5137 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5138 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5139 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5140 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5141 for (s = 0; s < size; ++s) { 5142 PetscInt r = 0; 5143 5144 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5145 if (support[s] >= cMax) { 5146 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 5147 5148 newSize += 1; 5149 } else { 5150 if (cone[1] == f) r = 1; 5151 else if (cone[2] == f) r = 2; 5152 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5153 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 5154 5155 newSize += 2; 5156 } 5157 } 5158 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5159 #if 1 5160 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5161 for (p = 0; p < newSize; ++p) { 5162 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); 5163 } 5164 #endif 5165 } 5166 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5167 break; 5168 default: 5169 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5170 } 5171 PetscFunctionReturn(0); 5172 } 5173 5174 #undef __FUNCT__ 5175 #define __FUNCT__ "CellRefinerSetCoordinates" 5176 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5177 { 5178 PetscSection coordSection, coordSectionNew; 5179 Vec coordinates, coordinatesNew; 5180 PetscScalar *coords, *coordsNew; 5181 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 5182 PetscErrorCode ierr; 5183 5184 PetscFunctionBegin; 5185 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5186 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5187 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5188 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5189 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5190 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 5191 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 5192 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5193 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 5194 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 5195 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 5196 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 5197 if (fMax < 0) fMax = fEnd; 5198 switch (refiner) { 5199 case 1: 5200 case 2: 5201 case 3: 5202 /* Simplicial and Hex 2D */ 5203 /* All vertices have the dim coordinates */ 5204 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 5205 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 5206 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 5207 } 5208 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 5209 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 5210 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5211 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 5212 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 5213 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 5214 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 5215 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 5216 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 5217 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5218 /* Old vertices have the same coordinates */ 5219 for (v = vStart; v < vEnd; ++v) { 5220 const PetscInt newv = vStartNew + (v - vStart); 5221 PetscInt off, offnew, d; 5222 5223 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5224 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5225 for (d = 0; d < dim; ++d) { 5226 coordsNew[offnew+d] = coords[off+d]; 5227 } 5228 } 5229 /* Face vertices have the average of endpoint coordinates */ 5230 for (f = fStart; f < fMax; ++f) { 5231 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5232 const PetscInt *cone; 5233 PetscInt coneSize, offA, offB, offnew, d; 5234 5235 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 5236 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 5237 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5238 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5239 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5240 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5241 for (d = 0; d < dim; ++d) { 5242 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 5243 } 5244 } 5245 /* Just Hex 2D */ 5246 if (refiner == 2) { 5247 /* Cell vertices have the average of corner coordinates */ 5248 for (c = cStart; c < cEnd; ++c) { 5249 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5250 PetscInt *cone = NULL; 5251 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 5252 5253 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5254 for (p = 0; p < closureSize*2; p += 2) { 5255 const PetscInt point = cone[p]; 5256 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 5257 } 5258 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 5259 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5260 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5261 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 5262 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 5263 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5264 for (d = 0; d < dim; ++d) { 5265 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 5266 } 5267 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5268 } 5269 } 5270 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 5271 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5272 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 5273 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 5274 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 5275 break; 5276 default: 5277 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5278 } 5279 PetscFunctionReturn(0); 5280 } 5281 5282 #undef __FUNCT__ 5283 #define __FUNCT__ "DMPlexCreateProcessSF" 5284 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 5285 { 5286 PetscInt numRoots, numLeaves, l; 5287 const PetscInt *localPoints; 5288 const PetscSFNode *remotePoints; 5289 PetscInt *localPointsNew; 5290 PetscSFNode *remotePointsNew; 5291 PetscInt *ranks, *ranksNew; 5292 PetscErrorCode ierr; 5293 5294 PetscFunctionBegin; 5295 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5296 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 5297 for (l = 0; l < numLeaves; ++l) { 5298 ranks[l] = remotePoints[l].rank; 5299 } 5300 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 5301 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 5302 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 5303 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 5304 for (l = 0; l < numLeaves; ++l) { 5305 ranksNew[l] = ranks[l]; 5306 localPointsNew[l] = l; 5307 remotePointsNew[l].index = 0; 5308 remotePointsNew[l].rank = ranksNew[l]; 5309 } 5310 ierr = PetscFree(ranks);CHKERRQ(ierr); 5311 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 5312 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 5313 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 5314 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 5315 PetscFunctionReturn(0); 5316 } 5317 5318 #undef __FUNCT__ 5319 #define __FUNCT__ "CellRefinerCreateSF" 5320 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5321 { 5322 PetscSF sf, sfNew, sfProcess; 5323 IS processRanks; 5324 MPI_Datatype depthType; 5325 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 5326 const PetscInt *localPoints, *neighbors; 5327 const PetscSFNode *remotePoints; 5328 PetscInt *localPointsNew; 5329 PetscSFNode *remotePointsNew; 5330 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 5331 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 5332 PetscErrorCode ierr; 5333 5334 PetscFunctionBegin; 5335 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 5336 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5337 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5338 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5339 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5340 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5341 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5342 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5343 switch (refiner) { 5344 case 3: 5345 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5346 cMax = PetscMin(cEnd, cMax); 5347 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5348 fMax = PetscMin(fEnd, fMax); 5349 } 5350 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 5351 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 5352 /* Caculate size of new SF */ 5353 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5354 if (numRoots < 0) PetscFunctionReturn(0); 5355 for (l = 0; l < numLeaves; ++l) { 5356 const PetscInt p = localPoints[l]; 5357 5358 switch (refiner) { 5359 case 1: 5360 /* Simplicial 2D */ 5361 if ((p >= vStart) && (p < vEnd)) { 5362 /* Old vertices stay the same */ 5363 ++numLeavesNew; 5364 } else if ((p >= fStart) && (p < fEnd)) { 5365 /* Old faces add new faces and vertex */ 5366 numLeavesNew += 1 + 2; 5367 } else if ((p >= cStart) && (p < cEnd)) { 5368 /* Old cells add new cells and interior faces */ 5369 numLeavesNew += 4 + 3; 5370 } 5371 break; 5372 case 2: 5373 /* Hex 2D */ 5374 if ((p >= vStart) && (p < vEnd)) { 5375 /* Old vertices stay the same */ 5376 ++numLeavesNew; 5377 } else if ((p >= fStart) && (p < fEnd)) { 5378 /* Old faces add new faces and vertex */ 5379 numLeavesNew += 1 + 2; 5380 } else if ((p >= cStart) && (p < cEnd)) { 5381 /* Old cells add new cells and interior faces */ 5382 numLeavesNew += 4 + 4; 5383 } 5384 break; 5385 default: 5386 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5387 } 5388 } 5389 /* Communicate depthSizes for each remote rank */ 5390 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 5391 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 5392 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 5393 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); 5394 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 5395 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 5396 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 5397 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 5398 for (n = 0; n < numNeighbors; ++n) { 5399 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 5400 } 5401 depthSizeOld[depth] = cMax; 5402 depthSizeOld[0] = vMax; 5403 depthSizeOld[depth-1] = fMax; 5404 depthSizeOld[1] = eMax; 5405 5406 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 5407 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 5408 5409 depthSizeOld[depth] = cEnd - cStart; 5410 depthSizeOld[0] = vEnd - vStart; 5411 depthSizeOld[depth-1] = fEnd - fStart; 5412 depthSizeOld[1] = eEnd - eStart; 5413 5414 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 5415 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 5416 for (n = 0; n < numNeighbors; ++n) { 5417 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 5418 } 5419 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 5420 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 5421 /* Calculate new point SF */ 5422 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 5423 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 5424 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 5425 for (l = 0, m = 0; l < numLeaves; ++l) { 5426 PetscInt p = localPoints[l]; 5427 PetscInt rp = remotePoints[l].index, n; 5428 PetscMPIInt rrank = remotePoints[l].rank; 5429 5430 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 5431 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 5432 switch (refiner) { 5433 case 1: 5434 /* Simplicial 2D */ 5435 if ((p >= vStart) && (p < vEnd)) { 5436 /* Old vertices stay the same */ 5437 localPointsNew[m] = vStartNew + (p - vStart); 5438 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5439 remotePointsNew[m].rank = rrank; 5440 ++m; 5441 } else if ((p >= fStart) && (p < fEnd)) { 5442 /* Old faces add new faces and vertex */ 5443 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5444 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5445 remotePointsNew[m].rank = rrank; 5446 ++m; 5447 for (r = 0; r < 2; ++r, ++m) { 5448 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5449 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5450 remotePointsNew[m].rank = rrank; 5451 } 5452 } else if ((p >= cStart) && (p < cEnd)) { 5453 /* Old cells add new cells and interior faces */ 5454 for (r = 0; r < 4; ++r, ++m) { 5455 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5456 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5457 remotePointsNew[m].rank = rrank; 5458 } 5459 for (r = 0; r < 3; ++r, ++m) { 5460 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5461 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 5462 remotePointsNew[m].rank = rrank; 5463 } 5464 } 5465 break; 5466 case 2: 5467 /* Hex 2D */ 5468 if ((p >= vStart) && (p < vEnd)) { 5469 /* Old vertices stay the same */ 5470 localPointsNew[m] = vStartNew + (p - vStart); 5471 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5472 remotePointsNew[m].rank = rrank; 5473 ++m; 5474 } else if ((p >= fStart) && (p < fEnd)) { 5475 /* Old faces add new faces and vertex */ 5476 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5477 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5478 remotePointsNew[m].rank = rrank; 5479 ++m; 5480 for (r = 0; r < 2; ++r, ++m) { 5481 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5482 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5483 remotePointsNew[m].rank = rrank; 5484 } 5485 } else if ((p >= cStart) && (p < cEnd)) { 5486 /* Old cells add new cells and interior faces */ 5487 for (r = 0; r < 4; ++r, ++m) { 5488 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5489 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5490 remotePointsNew[m].rank = rrank; 5491 } 5492 for (r = 0; r < 4; ++r, ++m) { 5493 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 5494 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 5495 remotePointsNew[m].rank = rrank; 5496 } 5497 } 5498 break; 5499 case 3: 5500 /* Hybrid simplicial 2D */ 5501 if ((p >= vStart) && (p < vEnd)) { 5502 /* Old vertices stay the same */ 5503 localPointsNew[m] = vStartNew + (p - vStart); 5504 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5505 remotePointsNew[m].rank = rrank; 5506 ++m; 5507 } else if ((p >= fStart) && (p < fMax)) { 5508 /* Old interior faces add new faces and vertex */ 5509 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5510 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5511 remotePointsNew[m].rank = rrank; 5512 ++m; 5513 for (r = 0; r < 2; ++r, ++m) { 5514 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5515 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5516 remotePointsNew[m].rank = rrank; 5517 } 5518 } else if ((p >= fMax) && (p < fEnd)) { 5519 /* Old hybrid faces stay the same */ 5520 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 5521 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 5522 remotePointsNew[m].rank = rrank; 5523 ++m; 5524 } else if ((p >= cStart) && (p < cMax)) { 5525 /* Old interior cells add new cells and interior faces */ 5526 for (r = 0; r < 4; ++r, ++m) { 5527 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5528 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5529 remotePointsNew[m].rank = rrank; 5530 } 5531 for (r = 0; r < 3; ++r, ++m) { 5532 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 5533 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 5534 remotePointsNew[m].rank = rrank; 5535 } 5536 } else if ((p >= cStart) && (p < cMax)) { 5537 /* Old hybrid cells add new cells and hybrid face */ 5538 for (r = 0; r < 2; ++r, ++m) { 5539 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5540 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5541 remotePointsNew[m].rank = rrank; 5542 } 5543 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 5544 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]); 5545 remotePointsNew[m].rank = rrank; 5546 ++m; 5547 } 5548 break; 5549 default: 5550 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5551 } 5552 } 5553 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 5554 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 5555 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 5556 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 5557 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 5558 PetscFunctionReturn(0); 5559 } 5560 5561 #undef __FUNCT__ 5562 #define __FUNCT__ "CellRefinerCreateLabels" 5563 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5564 { 5565 PetscInt numLabels, l; 5566 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 5567 PetscErrorCode ierr; 5568 5569 PetscFunctionBegin; 5570 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5571 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5572 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5573 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5574 5575 cStartNew = 0; 5576 vStartNew = depthSize[2]; 5577 fStartNew = depthSize[2] + depthSize[0]; 5578 5579 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 5580 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5581 switch (refiner) { 5582 case 3: 5583 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5584 cMax = PetscMin(cEnd, cMax); 5585 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5586 fMax = PetscMin(fEnd, fMax); 5587 } 5588 for (l = 0; l < numLabels; ++l) { 5589 DMLabel label, labelNew; 5590 const char *lname; 5591 PetscBool isDepth; 5592 IS valueIS; 5593 const PetscInt *values; 5594 PetscInt numValues, val; 5595 5596 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 5597 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 5598 if (isDepth) continue; 5599 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 5600 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 5601 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 5602 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 5603 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 5604 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 5605 for (val = 0; val < numValues; ++val) { 5606 IS pointIS; 5607 const PetscInt *points; 5608 PetscInt numPoints, n; 5609 5610 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 5611 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 5612 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 5613 for (n = 0; n < numPoints; ++n) { 5614 const PetscInt p = points[n]; 5615 switch (refiner) { 5616 case 1: 5617 /* Simplicial 2D */ 5618 if ((p >= vStart) && (p < vEnd)) { 5619 /* Old vertices stay the same */ 5620 newp = vStartNew + (p - vStart); 5621 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5622 } else if ((p >= fStart) && (p < fEnd)) { 5623 /* Old faces add new faces and vertex */ 5624 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5625 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5626 for (r = 0; r < 2; ++r) { 5627 newp = fStartNew + (p - fStart)*2 + r; 5628 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5629 } 5630 } else if ((p >= cStart) && (p < cEnd)) { 5631 /* Old cells add new cells and interior faces */ 5632 for (r = 0; r < 4; ++r) { 5633 newp = cStartNew + (p - cStart)*4 + r; 5634 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5635 } 5636 for (r = 0; r < 3; ++r) { 5637 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5638 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5639 } 5640 } 5641 break; 5642 case 2: 5643 /* Hex 2D */ 5644 if ((p >= vStart) && (p < vEnd)) { 5645 /* Old vertices stay the same */ 5646 newp = vStartNew + (p - vStart); 5647 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5648 } else if ((p >= fStart) && (p < fEnd)) { 5649 /* Old faces add new faces and vertex */ 5650 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5651 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5652 for (r = 0; r < 2; ++r) { 5653 newp = fStartNew + (p - fStart)*2 + r; 5654 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5655 } 5656 } else if ((p >= cStart) && (p < cEnd)) { 5657 /* Old cells add new cells and interior faces and vertex */ 5658 for (r = 0; r < 4; ++r) { 5659 newp = cStartNew + (p - cStart)*4 + r; 5660 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5661 } 5662 for (r = 0; r < 4; ++r) { 5663 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 5664 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5665 } 5666 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 5667 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5668 } 5669 break; 5670 case 3: 5671 /* Hybrid simplicial 2D */ 5672 if ((p >= vStart) && (p < vEnd)) { 5673 /* Old vertices stay the same */ 5674 newp = vStartNew + (p - vStart); 5675 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5676 } else if ((p >= fStart) && (p < fMax)) { 5677 /* Old interior faces add new faces and vertex */ 5678 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5679 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5680 for (r = 0; r < 2; ++r) { 5681 newp = fStartNew + (p - fStart)*2 + r; 5682 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5683 } 5684 } else if ((p >= fMax) && (p < fEnd)) { 5685 /* Old hybrid faces stay the same */ 5686 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 5687 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5688 } else if ((p >= cStart) && (p < cMax)) { 5689 /* Old interior cells add new cells and interior faces */ 5690 for (r = 0; r < 4; ++r) { 5691 newp = cStartNew + (p - cStart)*4 + r; 5692 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5693 } 5694 for (r = 0; r < 3; ++r) { 5695 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5696 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5697 } 5698 } else if ((p >= cMax) && (p < cEnd)) { 5699 /* Old hybrid cells add new cells and hybrid face */ 5700 for (r = 0; r < 2; ++r) { 5701 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 5702 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5703 } 5704 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 5705 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5706 } 5707 break; 5708 default: 5709 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5710 } 5711 } 5712 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 5713 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 5714 } 5715 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 5716 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 5717 if (0) { 5718 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 5719 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 5720 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 5721 } 5722 } 5723 PetscFunctionReturn(0); 5724 } 5725 5726 #undef __FUNCT__ 5727 #define __FUNCT__ "DMPlexRefine_Uniform" 5728 /* This will only work for interpolated meshes */ 5729 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 5730 { 5731 DM rdm; 5732 PetscInt *depthSize; 5733 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 5734 PetscErrorCode ierr; 5735 5736 PetscFunctionBegin; 5737 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 5738 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 5739 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5740 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 5741 /* Calculate number of new points of each depth */ 5742 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5743 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 5744 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 5745 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 5746 /* Step 1: Set chart */ 5747 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 5748 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 5749 /* Step 2: Set cone/support sizes */ 5750 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5751 /* Step 3: Setup refined DM */ 5752 ierr = DMSetUp(rdm);CHKERRQ(ierr); 5753 /* Step 4: Set cones and supports */ 5754 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5755 /* Step 5: Stratify */ 5756 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 5757 /* Step 6: Set coordinates for vertices */ 5758 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5759 /* Step 7: Create pointSF */ 5760 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5761 /* Step 8: Create labels */ 5762 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5763 ierr = PetscFree(depthSize);CHKERRQ(ierr); 5764 5765 *dmRefined = rdm; 5766 PetscFunctionReturn(0); 5767 } 5768 5769 #undef __FUNCT__ 5770 #define __FUNCT__ "DMPlexSetRefinementUniform" 5771 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 5772 { 5773 DM_Plex *mesh = (DM_Plex*) dm->data; 5774 5775 PetscFunctionBegin; 5776 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5777 mesh->refinementUniform = refinementUniform; 5778 PetscFunctionReturn(0); 5779 } 5780 5781 #undef __FUNCT__ 5782 #define __FUNCT__ "DMPlexGetRefinementUniform" 5783 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 5784 { 5785 DM_Plex *mesh = (DM_Plex*) dm->data; 5786 5787 PetscFunctionBegin; 5788 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5789 PetscValidPointer(refinementUniform, 2); 5790 *refinementUniform = mesh->refinementUniform; 5791 PetscFunctionReturn(0); 5792 } 5793 5794 #undef __FUNCT__ 5795 #define __FUNCT__ "DMPlexSetRefinementLimit" 5796 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 5797 { 5798 DM_Plex *mesh = (DM_Plex*) dm->data; 5799 5800 PetscFunctionBegin; 5801 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5802 mesh->refinementLimit = refinementLimit; 5803 PetscFunctionReturn(0); 5804 } 5805 5806 #undef __FUNCT__ 5807 #define __FUNCT__ "DMPlexGetRefinementLimit" 5808 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 5809 { 5810 DM_Plex *mesh = (DM_Plex*) dm->data; 5811 5812 PetscFunctionBegin; 5813 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5814 PetscValidPointer(refinementLimit, 2); 5815 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 5816 *refinementLimit = mesh->refinementLimit; 5817 PetscFunctionReturn(0); 5818 } 5819 5820 #undef __FUNCT__ 5821 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 5822 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 5823 { 5824 PetscInt dim, cStart, coneSize, cMax; 5825 PetscErrorCode ierr; 5826 5827 PetscFunctionBegin; 5828 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5829 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 5830 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 5831 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5832 switch (dim) { 5833 case 2: 5834 switch (coneSize) { 5835 case 3: 5836 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 5837 else *cellRefiner = 1; /* Triangular */ 5838 break; 5839 case 4: 5840 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 5841 else *cellRefiner = 2; /* Quadrilateral */ 5842 break; 5843 default: 5844 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 5845 } 5846 break; 5847 default: 5848 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 5849 } 5850 PetscFunctionReturn(0); 5851 } 5852 5853 #undef __FUNCT__ 5854 #define __FUNCT__ "DMRefine_Plex" 5855 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 5856 { 5857 PetscReal refinementLimit; 5858 PetscInt dim, cStart, cEnd; 5859 char genname[1024], *name = NULL; 5860 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5861 PetscErrorCode ierr; 5862 5863 PetscFunctionBegin; 5864 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 5865 if (isUniform) { 5866 CellRefiner cellRefiner; 5867 5868 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 5869 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 5870 PetscFunctionReturn(0); 5871 } 5872 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 5873 if (refinementLimit == 0.0) PetscFunctionReturn(0); 5874 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5875 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5876 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5877 if (flg) name = genname; 5878 if (name) { 5879 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5880 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5881 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5882 } 5883 switch (dim) { 5884 case 2: 5885 if (!name || isTriangle) { 5886 #if defined(PETSC_HAVE_TRIANGLE) 5887 double *maxVolumes; 5888 PetscInt c; 5889 5890 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 5891 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5892 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5893 #else 5894 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 5895 #endif 5896 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5897 break; 5898 case 3: 5899 if (!name || isCTetgen) { 5900 #if defined(PETSC_HAVE_CTETGEN) 5901 PetscReal *maxVolumes; 5902 PetscInt c; 5903 5904 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 5905 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5906 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5907 #else 5908 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5909 #endif 5910 } else if (isTetgen) { 5911 #if defined(PETSC_HAVE_TETGEN) 5912 double *maxVolumes; 5913 PetscInt c; 5914 5915 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 5916 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5917 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5918 #else 5919 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5920 #endif 5921 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5922 break; 5923 default: 5924 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 5925 } 5926 PetscFunctionReturn(0); 5927 } 5928 5929 #undef __FUNCT__ 5930 #define __FUNCT__ "DMPlexGetDepth" 5931 /*@ 5932 DMPlexGetDepth - get the number of strata 5933 5934 Not Collective 5935 5936 Input Parameters: 5937 . dm - The DMPlex object 5938 5939 Output Parameters: 5940 . depth - number of strata 5941 5942 Level: developer 5943 5944 Notes: 5945 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 5946 5947 .keywords: mesh, points 5948 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 5949 @*/ 5950 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5951 { 5952 PetscInt d; 5953 PetscErrorCode ierr; 5954 5955 PetscFunctionBegin; 5956 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5957 PetscValidPointer(depth, 2); 5958 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 5959 *depth = d-1; 5960 PetscFunctionReturn(0); 5961 } 5962 5963 #undef __FUNCT__ 5964 #define __FUNCT__ "DMPlexGetDepthStratum" 5965 /*@ 5966 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 5967 5968 Not Collective 5969 5970 Input Parameters: 5971 + dm - The DMPlex object 5972 - stratumValue - The requested depth 5973 5974 Output Parameters: 5975 + start - The first point at this depth 5976 - end - One beyond the last point at this depth 5977 5978 Level: developer 5979 5980 .keywords: mesh, points 5981 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 5982 @*/ 5983 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 5984 { 5985 DM_Plex *mesh = (DM_Plex*) dm->data; 5986 DMLabel next = mesh->labels; 5987 PetscBool flg = PETSC_FALSE; 5988 PetscInt depth; 5989 PetscErrorCode ierr; 5990 5991 PetscFunctionBegin; 5992 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5993 if (stratumValue < 0) { 5994 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 5995 PetscFunctionReturn(0); 5996 } else { 5997 PetscInt pStart, pEnd; 5998 5999 if (start) *start = 0; 6000 if (end) *end = 0; 6001 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6002 if (pStart == pEnd) PetscFunctionReturn(0); 6003 } 6004 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6005 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6006 /* We should have a generic GetLabel() and a Label class */ 6007 while (next) { 6008 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6009 if (flg) break; 6010 next = next->next; 6011 } 6012 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6013 depth = stratumValue; 6014 if ((depth < 0) || (depth >= next->numStrata)) { 6015 if (start) *start = 0; 6016 if (end) *end = 0; 6017 } else { 6018 if (start) *start = next->points[next->stratumOffsets[depth]]; 6019 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 6020 } 6021 PetscFunctionReturn(0); 6022 } 6023 6024 #undef __FUNCT__ 6025 #define __FUNCT__ "DMPlexGetHeightStratum" 6026 /*@ 6027 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 6028 6029 Not Collective 6030 6031 Input Parameters: 6032 + dm - The DMPlex object 6033 - stratumValue - The requested height 6034 6035 Output Parameters: 6036 + start - The first point at this height 6037 - end - One beyond the last point at this height 6038 6039 Level: developer 6040 6041 .keywords: mesh, points 6042 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 6043 @*/ 6044 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 6045 { 6046 DM_Plex *mesh = (DM_Plex*) dm->data; 6047 DMLabel next = mesh->labels; 6048 PetscBool flg = PETSC_FALSE; 6049 PetscInt depth; 6050 PetscErrorCode ierr; 6051 6052 PetscFunctionBegin; 6053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6054 if (stratumValue < 0) { 6055 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 6056 } else { 6057 PetscInt pStart, pEnd; 6058 6059 if (start) *start = 0; 6060 if (end) *end = 0; 6061 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6062 if (pStart == pEnd) PetscFunctionReturn(0); 6063 } 6064 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6065 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6066 /* We should have a generic GetLabel() and a Label class */ 6067 while (next) { 6068 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6069 if (flg) break; 6070 next = next->next; 6071 } 6072 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6073 depth = next->stratumValues[next->numStrata-1] - stratumValue; 6074 if ((depth < 0) || (depth >= next->numStrata)) { 6075 if (start) *start = 0; 6076 if (end) *end = 0; 6077 } else { 6078 if (start) *start = next->points[next->stratumOffsets[depth]]; 6079 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 6080 } 6081 PetscFunctionReturn(0); 6082 } 6083 6084 #undef __FUNCT__ 6085 #define __FUNCT__ "DMPlexCreateSectionInitial" 6086 /* Set the number of dof on each point and separate by fields */ 6087 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 6088 { 6089 PetscInt *numDofTot; 6090 PetscInt pStart = 0, pEnd = 0; 6091 PetscInt p, d, f; 6092 PetscErrorCode ierr; 6093 6094 PetscFunctionBegin; 6095 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 6096 for (d = 0; d <= dim; ++d) { 6097 numDofTot[d] = 0; 6098 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 6099 } 6100 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 6101 if (numFields > 0) { 6102 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 6103 if (numComp) { 6104 for (f = 0; f < numFields; ++f) { 6105 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 6106 } 6107 } 6108 } 6109 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6110 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 6111 for (d = 0; d <= dim; ++d) { 6112 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 6113 for (p = pStart; p < pEnd; ++p) { 6114 for (f = 0; f < numFields; ++f) { 6115 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 6116 } 6117 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 6118 } 6119 } 6120 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 6121 PetscFunctionReturn(0); 6122 } 6123 6124 #undef __FUNCT__ 6125 #define __FUNCT__ "DMPlexCreateSectionBCDof" 6126 /* Set the number of dof on each point and separate by fields 6127 If constDof is PETSC_DETERMINE, constrain every dof on the point 6128 */ 6129 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 6130 { 6131 PetscInt numFields; 6132 PetscInt bc; 6133 PetscErrorCode ierr; 6134 6135 PetscFunctionBegin; 6136 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6137 for (bc = 0; bc < numBC; ++bc) { 6138 PetscInt field = 0; 6139 const PetscInt *idx; 6140 PetscInt n, i; 6141 6142 if (numFields) field = bcField[bc]; 6143 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 6144 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6145 for (i = 0; i < n; ++i) { 6146 const PetscInt p = idx[i]; 6147 PetscInt numConst = constDof; 6148 6149 /* Constrain every dof on the point */ 6150 if (numConst < 0) { 6151 if (numFields) { 6152 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 6153 } else { 6154 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 6155 } 6156 } 6157 if (numFields) { 6158 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 6159 } 6160 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 6161 } 6162 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6163 } 6164 PetscFunctionReturn(0); 6165 } 6166 6167 #undef __FUNCT__ 6168 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 6169 /* Set the constrained indices on each point and separate by fields */ 6170 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 6171 { 6172 PetscInt *maxConstraints; 6173 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 6174 PetscErrorCode ierr; 6175 6176 PetscFunctionBegin; 6177 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6178 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6179 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 6180 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 6181 for (p = pStart; p < pEnd; ++p) { 6182 PetscInt cdof; 6183 6184 if (numFields) { 6185 for (f = 0; f < numFields; ++f) { 6186 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 6187 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 6188 } 6189 } else { 6190 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6191 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 6192 } 6193 } 6194 for (f = 0; f < numFields; ++f) { 6195 maxConstraints[numFields] += maxConstraints[f]; 6196 } 6197 if (maxConstraints[numFields]) { 6198 PetscInt *indices; 6199 6200 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 6201 for (p = pStart; p < pEnd; ++p) { 6202 PetscInt cdof, d; 6203 6204 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6205 if (cdof) { 6206 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 6207 if (numFields) { 6208 PetscInt numConst = 0, foff = 0; 6209 6210 for (f = 0; f < numFields; ++f) { 6211 PetscInt cfdof, fdof; 6212 6213 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 6214 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 6215 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 6216 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 6217 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 6218 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 6219 numConst += cfdof; 6220 foff += fdof; 6221 } 6222 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 6223 } else { 6224 for (d = 0; d < cdof; ++d) indices[d] = d; 6225 } 6226 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 6227 } 6228 } 6229 ierr = PetscFree(indices);CHKERRQ(ierr); 6230 } 6231 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 6232 PetscFunctionReturn(0); 6233 } 6234 6235 #undef __FUNCT__ 6236 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 6237 /* Set the constrained field indices on each point */ 6238 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 6239 { 6240 const PetscInt *points, *indices; 6241 PetscInt numFields, maxDof, numPoints, p, numConstraints; 6242 PetscErrorCode ierr; 6243 6244 PetscFunctionBegin; 6245 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6246 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 6247 6248 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 6249 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 6250 if (!constraintIndices) { 6251 PetscInt *idx, i; 6252 6253 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6254 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 6255 for (i = 0; i < maxDof; ++i) idx[i] = i; 6256 for (p = 0; p < numPoints; ++p) { 6257 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 6258 } 6259 ierr = PetscFree(idx);CHKERRQ(ierr); 6260 } else { 6261 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 6262 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 6263 for (p = 0; p < numPoints; ++p) { 6264 PetscInt fcdof; 6265 6266 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 6267 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); 6268 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 6269 } 6270 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 6271 } 6272 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 6273 PetscFunctionReturn(0); 6274 } 6275 6276 #undef __FUNCT__ 6277 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 6278 /* Set the constrained indices on each point and separate by fields */ 6279 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 6280 { 6281 PetscInt *indices; 6282 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 6283 PetscErrorCode ierr; 6284 6285 PetscFunctionBegin; 6286 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6287 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 6288 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6289 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 6290 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6291 for (p = pStart; p < pEnd; ++p) { 6292 PetscInt cdof, d; 6293 6294 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6295 if (cdof) { 6296 PetscInt numConst = 0, foff = 0; 6297 6298 for (f = 0; f < numFields; ++f) { 6299 const PetscInt *fcind; 6300 PetscInt fdof, fcdof; 6301 6302 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 6303 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 6304 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 6305 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 6306 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 6307 foff += fdof; 6308 numConst += fcdof; 6309 } 6310 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 6311 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 6312 } 6313 } 6314 ierr = PetscFree(indices);CHKERRQ(ierr); 6315 PetscFunctionReturn(0); 6316 } 6317 6318 #undef __FUNCT__ 6319 #define __FUNCT__ "DMPlexCreateSection" 6320 /*@C 6321 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 6322 6323 Not Collective 6324 6325 Input Parameters: 6326 + dm - The DMPlex object 6327 . dim - The spatial dimension of the problem 6328 . numFields - The number of fields in the problem 6329 . numComp - An array of size numFields that holds the number of components for each field 6330 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 6331 . numBC - The number of boundary conditions 6332 . bcField - An array of size numBC giving the field number for each boundry condition 6333 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 6334 6335 Output Parameter: 6336 . section - The PetscSection object 6337 6338 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 6339 nubmer of dof for field 0 on each edge. 6340 6341 Level: developer 6342 6343 Fortran Notes: 6344 A Fortran 90 version is available as DMPlexCreateSectionF90() 6345 6346 .keywords: mesh, elements 6347 .seealso: DMPlexCreate(), PetscSectionCreate() 6348 @*/ 6349 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 6350 { 6351 PetscErrorCode ierr; 6352 6353 PetscFunctionBegin; 6354 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 6355 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 6356 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 6357 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 6358 { 6359 PetscBool view = PETSC_FALSE; 6360 6361 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 6362 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 6363 } 6364 PetscFunctionReturn(0); 6365 } 6366 6367 #undef __FUNCT__ 6368 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 6369 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 6370 { 6371 PetscSection section; 6372 PetscErrorCode ierr; 6373 6374 PetscFunctionBegin; 6375 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 6376 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6377 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 6378 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6379 PetscFunctionReturn(0); 6380 } 6381 6382 #undef __FUNCT__ 6383 #define __FUNCT__ "DMPlexGetCoordinateSection" 6384 /*@ 6385 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6386 6387 Not Collective 6388 6389 Input Parameter: 6390 . dm - The DMPlex object 6391 6392 Output Parameter: 6393 . section - The PetscSection object 6394 6395 Level: intermediate 6396 6397 .keywords: mesh, coordinates 6398 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6399 @*/ 6400 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 6401 { 6402 DM cdm; 6403 PetscErrorCode ierr; 6404 6405 PetscFunctionBegin; 6406 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6407 PetscValidPointer(section, 2); 6408 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6409 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 6410 PetscFunctionReturn(0); 6411 } 6412 6413 #undef __FUNCT__ 6414 #define __FUNCT__ "DMPlexSetCoordinateSection" 6415 /*@ 6416 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 6417 6418 Not Collective 6419 6420 Input Parameters: 6421 + dm - The DMPlex object 6422 - section - The PetscSection object 6423 6424 Level: intermediate 6425 6426 .keywords: mesh, coordinates 6427 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6428 @*/ 6429 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 6430 { 6431 DM cdm; 6432 PetscErrorCode ierr; 6433 6434 PetscFunctionBegin; 6435 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6436 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 6437 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6438 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 6439 PetscFunctionReturn(0); 6440 } 6441 6442 #undef __FUNCT__ 6443 #define __FUNCT__ "DMPlexGetConeSection" 6444 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 6445 { 6446 DM_Plex *mesh = (DM_Plex*) dm->data; 6447 6448 PetscFunctionBegin; 6449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6450 if (section) *section = mesh->coneSection; 6451 PetscFunctionReturn(0); 6452 } 6453 6454 #undef __FUNCT__ 6455 #define __FUNCT__ "DMPlexGetCones" 6456 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 6457 { 6458 DM_Plex *mesh = (DM_Plex*) dm->data; 6459 6460 PetscFunctionBegin; 6461 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6462 if (cones) *cones = mesh->cones; 6463 PetscFunctionReturn(0); 6464 } 6465 6466 #undef __FUNCT__ 6467 #define __FUNCT__ "DMPlexGetConeOrientations" 6468 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 6469 { 6470 DM_Plex *mesh = (DM_Plex*) dm->data; 6471 6472 PetscFunctionBegin; 6473 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6474 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 6475 PetscFunctionReturn(0); 6476 } 6477 6478 /******************************** FEM Support **********************************/ 6479 6480 #undef __FUNCT__ 6481 #define __FUNCT__ "DMPlexVecGetClosure" 6482 /*@C 6483 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6484 6485 Not collective 6486 6487 Input Parameters: 6488 + dm - The DM 6489 . section - The section describing the layout in v, or NULL to use the default section 6490 . v - The local vector 6491 - point - The sieve point in the DM 6492 6493 Output Parameters: 6494 + csize - The number of values in the closure, or NULL 6495 - values - The array of values, which is a borrowed array and should not be freed 6496 6497 Fortran Notes: 6498 Since it returns an array, this routine is only available in Fortran 90, and you must 6499 include petsc.h90 in your code. 6500 6501 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6502 6503 Level: intermediate 6504 6505 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6506 @*/ 6507 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6508 { 6509 PetscScalar *array, *vArray; 6510 PetscInt *points = NULL; 6511 PetscInt offsets[32]; 6512 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 6513 PetscErrorCode ierr; 6514 6515 PetscFunctionBegin; 6516 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6517 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6518 if (!section) { 6519 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6520 } 6521 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6522 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6523 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6524 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6525 /* Compress out points not in the section */ 6526 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6527 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6528 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6529 points[q*2] = points[p]; 6530 points[q*2+1] = points[p+1]; 6531 ++q; 6532 } 6533 } 6534 numPoints = q; 6535 for (p = 0, size = 0; p < numPoints*2; p += 2) { 6536 PetscInt dof, fdof; 6537 6538 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6539 for (f = 0; f < numFields; ++f) { 6540 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6541 offsets[f+1] += fdof; 6542 } 6543 size += dof; 6544 } 6545 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6546 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 6547 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 6548 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 6549 for (p = 0; p < numPoints*2; p += 2) { 6550 PetscInt o = points[p+1]; 6551 PetscInt dof, off, d; 6552 PetscScalar *varr; 6553 6554 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6555 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 6556 varr = &vArray[off]; 6557 if (numFields) { 6558 PetscInt fdof, foff, fcomp, f, c; 6559 6560 for (f = 0, foff = 0; f < numFields; ++f) { 6561 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6562 if (o >= 0) { 6563 for (d = 0; d < fdof; ++d, ++offsets[f]) { 6564 array[offsets[f]] = varr[foff+d]; 6565 } 6566 } else { 6567 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6568 for (d = fdof/fcomp-1; d >= 0; --d) { 6569 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 6570 array[offsets[f]] = varr[foff+d*fcomp+c]; 6571 } 6572 } 6573 } 6574 foff += fdof; 6575 } 6576 } else { 6577 if (o >= 0) { 6578 for (d = 0; d < dof; ++d, ++offsets[0]) { 6579 array[offsets[0]] = varr[d]; 6580 } 6581 } else { 6582 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 6583 array[offsets[0]] = varr[d]; 6584 } 6585 } 6586 } 6587 } 6588 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6589 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 6590 if (csize) *csize = size; 6591 *values = array; 6592 PetscFunctionReturn(0); 6593 } 6594 6595 #undef __FUNCT__ 6596 #define __FUNCT__ "DMPlexVecRestoreClosure" 6597 /*@C 6598 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6599 6600 Not collective 6601 6602 Input Parameters: 6603 + dm - The DM 6604 . section - The section describing the layout in v, or NULL to use the default section 6605 . v - The local vector 6606 . point - The sieve point in the DM 6607 . csize - The number of values in the closure, or NULL 6608 - values - The array of values, which is a borrowed array and should not be freed 6609 6610 Fortran Notes: 6611 Since it returns an array, this routine is only available in Fortran 90, and you must 6612 include petsc.h90 in your code. 6613 6614 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6615 6616 Level: intermediate 6617 6618 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6619 @*/ 6620 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6621 { 6622 PetscInt size = 0; 6623 PetscErrorCode ierr; 6624 6625 PetscFunctionBegin; 6626 /* Should work without recalculating size */ 6627 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 6628 PetscFunctionReturn(0); 6629 } 6630 6631 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 6632 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 6633 6634 #undef __FUNCT__ 6635 #define __FUNCT__ "updatePoint_private" 6636 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6637 { 6638 PetscInt cdof; /* The number of constraints on this point */ 6639 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6640 PetscScalar *a; 6641 PetscInt off, cind = 0, k; 6642 PetscErrorCode ierr; 6643 6644 PetscFunctionBegin; 6645 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6646 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6647 a = &array[off]; 6648 if (!cdof || setBC) { 6649 if (orientation >= 0) { 6650 for (k = 0; k < dof; ++k) { 6651 fuse(&a[k], values[k]); 6652 } 6653 } else { 6654 for (k = 0; k < dof; ++k) { 6655 fuse(&a[k], values[dof-k-1]); 6656 } 6657 } 6658 } else { 6659 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6660 if (orientation >= 0) { 6661 for (k = 0; k < dof; ++k) { 6662 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6663 fuse(&a[k], values[k]); 6664 } 6665 } else { 6666 for (k = 0; k < dof; ++k) { 6667 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6668 fuse(&a[k], values[dof-k-1]); 6669 } 6670 } 6671 } 6672 PetscFunctionReturn(0); 6673 } 6674 6675 #undef __FUNCT__ 6676 #define __FUNCT__ "updatePointFields_private" 6677 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6678 { 6679 PetscScalar *a; 6680 PetscInt numFields, off, foff, f; 6681 PetscErrorCode ierr; 6682 6683 PetscFunctionBegin; 6684 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6685 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6686 a = &array[off]; 6687 for (f = 0, foff = 0; f < numFields; ++f) { 6688 PetscInt fdof, fcomp, fcdof; 6689 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6690 PetscInt cind = 0, k, c; 6691 6692 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6693 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6694 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6695 if (!fcdof || setBC) { 6696 if (orientation >= 0) { 6697 for (k = 0; k < fdof; ++k) { 6698 fuse(&a[foff+k], values[foffs[f]+k]); 6699 } 6700 } else { 6701 for (k = fdof/fcomp-1; k >= 0; --k) { 6702 for (c = 0; c < fcomp; ++c) { 6703 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6704 } 6705 } 6706 } 6707 } else { 6708 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6709 if (orientation >= 0) { 6710 for (k = 0; k < fdof; ++k) { 6711 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 6712 fuse(&a[foff+k], values[foffs[f]+k]); 6713 } 6714 } else { 6715 for (k = fdof/fcomp-1; k >= 0; --k) { 6716 for (c = 0; c < fcomp; ++c) { 6717 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 6718 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6719 } 6720 } 6721 } 6722 } 6723 foff += fdof; 6724 foffs[f] += fdof; 6725 } 6726 PetscFunctionReturn(0); 6727 } 6728 6729 #undef __FUNCT__ 6730 #define __FUNCT__ "DMPlexVecSetClosure" 6731 /*@C 6732 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6733 6734 Not collective 6735 6736 Input Parameters: 6737 + dm - The DM 6738 . section - The section describing the layout in v, or NULL to use the default section 6739 . v - The local vector 6740 . point - The sieve point in the DM 6741 . values - The array of values 6742 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6743 6744 Fortran Notes: 6745 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6746 6747 Level: intermediate 6748 6749 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6750 @*/ 6751 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6752 { 6753 PetscScalar *array; 6754 PetscInt *points = NULL; 6755 PetscInt offsets[32]; 6756 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 6757 PetscErrorCode ierr; 6758 6759 PetscFunctionBegin; 6760 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6761 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6762 if (!section) { 6763 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6764 } 6765 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6766 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6767 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6768 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6769 /* Compress out points not in the section */ 6770 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6771 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6772 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6773 points[q*2] = points[p]; 6774 points[q*2+1] = points[p+1]; 6775 ++q; 6776 } 6777 } 6778 numPoints = q; 6779 for (p = 0; p < numPoints*2; p += 2) { 6780 PetscInt fdof; 6781 6782 for (f = 0; f < numFields; ++f) { 6783 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6784 offsets[f+1] += fdof; 6785 } 6786 } 6787 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6788 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6789 if (numFields) { 6790 switch (mode) { 6791 case INSERT_VALUES: 6792 for (p = 0; p < numPoints*2; p += 2) { 6793 PetscInt o = points[p+1]; 6794 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 6795 } break; 6796 case INSERT_ALL_VALUES: 6797 for (p = 0; p < numPoints*2; p += 2) { 6798 PetscInt o = points[p+1]; 6799 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 6800 } break; 6801 case ADD_VALUES: 6802 for (p = 0; p < numPoints*2; p += 2) { 6803 PetscInt o = points[p+1]; 6804 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 6805 } break; 6806 case ADD_ALL_VALUES: 6807 for (p = 0; p < numPoints*2; p += 2) { 6808 PetscInt o = points[p+1]; 6809 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 6810 } break; 6811 default: 6812 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 6813 } 6814 } else { 6815 switch (mode) { 6816 case INSERT_VALUES: 6817 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6818 PetscInt o = points[p+1]; 6819 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6820 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 6821 } break; 6822 case INSERT_ALL_VALUES: 6823 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6824 PetscInt o = points[p+1]; 6825 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6826 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 6827 } break; 6828 case ADD_VALUES: 6829 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6830 PetscInt o = points[p+1]; 6831 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6832 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 6833 } break; 6834 case ADD_ALL_VALUES: 6835 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6836 PetscInt o = points[p+1]; 6837 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6838 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 6839 } break; 6840 default: 6841 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 6842 } 6843 } 6844 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6845 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6846 PetscFunctionReturn(0); 6847 } 6848 6849 #undef __FUNCT__ 6850 #define __FUNCT__ "DMPlexPrintMatSetValues" 6851 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], const PetscScalar values[]) 6852 { 6853 PetscMPIInt rank; 6854 PetscInt i, j; 6855 PetscErrorCode ierr; 6856 6857 PetscFunctionBegin; 6858 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 6859 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 6860 for (i = 0; i < numIndices; i++) { 6861 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 6862 } 6863 for (i = 0; i < numIndices; i++) { 6864 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 6865 for (j = 0; j < numIndices; j++) { 6866 #if defined(PETSC_USE_COMPLEX) 6867 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 6868 #else 6869 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 6870 #endif 6871 } 6872 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6873 } 6874 PetscFunctionReturn(0); 6875 } 6876 6877 #undef __FUNCT__ 6878 #define __FUNCT__ "indicesPoint_private" 6879 /* . off - The global offset of this point */ 6880 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 6881 { 6882 PetscInt dof; /* The number of unknowns on this point */ 6883 PetscInt cdof; /* The number of constraints on this point */ 6884 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6885 PetscInt cind = 0, k; 6886 PetscErrorCode ierr; 6887 6888 PetscFunctionBegin; 6889 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6890 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6891 if (!cdof || setBC) { 6892 if (orientation >= 0) { 6893 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 6894 } else { 6895 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 6896 } 6897 } else { 6898 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6899 if (orientation >= 0) { 6900 for (k = 0; k < dof; ++k) { 6901 if ((cind < cdof) && (k == cdofs[cind])) { 6902 /* Insert check for returning constrained indices */ 6903 indices[*loff+k] = -(off+k+1); 6904 ++cind; 6905 } else { 6906 indices[*loff+k] = off+k-cind; 6907 } 6908 } 6909 } else { 6910 for (k = 0; k < dof; ++k) { 6911 if ((cind < cdof) && (k == cdofs[cind])) { 6912 /* Insert check for returning constrained indices */ 6913 indices[*loff+dof-k-1] = -(off+k+1); 6914 ++cind; 6915 } else { 6916 indices[*loff+dof-k-1] = off+k-cind; 6917 } 6918 } 6919 } 6920 } 6921 *loff += dof; 6922 PetscFunctionReturn(0); 6923 } 6924 6925 #undef __FUNCT__ 6926 #define __FUNCT__ "indicesPointFields_private" 6927 /* . off - The global offset of this point */ 6928 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 6929 { 6930 PetscInt numFields, foff, f; 6931 PetscErrorCode ierr; 6932 6933 PetscFunctionBegin; 6934 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6935 for (f = 0, foff = 0; f < numFields; ++f) { 6936 PetscInt fdof, fcomp, cfdof; 6937 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6938 PetscInt cind = 0, k, c; 6939 6940 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6941 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6942 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6943 if (!cfdof || setBC) { 6944 if (orientation >= 0) { 6945 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 6946 } else { 6947 for (k = fdof/fcomp-1; k >= 0; --k) { 6948 for (c = 0; c < fcomp; ++c) { 6949 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 6950 } 6951 } 6952 } 6953 } else { 6954 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6955 if (orientation >= 0) { 6956 for (k = 0; k < fdof; ++k) { 6957 if ((cind < cfdof) && (k == fcdofs[cind])) { 6958 indices[foffs[f]+k] = -(off+foff+k+1); 6959 ++cind; 6960 } else { 6961 indices[foffs[f]+k] = off+foff+k-cind; 6962 } 6963 } 6964 } else { 6965 for (k = fdof/fcomp-1; k >= 0; --k) { 6966 for (c = 0; c < fcomp; ++c) { 6967 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 6968 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 6969 ++cind; 6970 } else { 6971 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 6972 } 6973 } 6974 } 6975 } 6976 } 6977 foff += fdof - cfdof; 6978 foffs[f] += fdof; 6979 } 6980 PetscFunctionReturn(0); 6981 } 6982 6983 #undef __FUNCT__ 6984 #define __FUNCT__ "DMPlexMatSetClosure" 6985 /*@C 6986 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 6987 6988 Not collective 6989 6990 Input Parameters: 6991 + dm - The DM 6992 . section - The section describing the layout in v, or NULL to use the default section 6993 . globalSection - The section describing the layout in v, or NULL to use the default section 6994 . A - The matrix 6995 . point - The sieve point in the DM 6996 . values - The array of values 6997 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6998 6999 Fortran Notes: 7000 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7001 7002 Level: intermediate 7003 7004 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 7005 @*/ 7006 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7007 { 7008 DM_Plex *mesh = (DM_Plex*) dm->data; 7009 PetscInt *points = NULL; 7010 PetscInt *indices; 7011 PetscInt offsets[32]; 7012 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 7013 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 7014 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 7015 PetscErrorCode ierr; 7016 7017 PetscFunctionBegin; 7018 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7019 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 7020 if (useDefault) { 7021 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7022 } 7023 if (useGlobalDefault) { 7024 if (useDefault) { 7025 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 7026 } else { 7027 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7028 } 7029 } 7030 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7031 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7032 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7033 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7034 /* Compress out points not in the section */ 7035 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7036 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7037 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7038 points[q*2] = points[p]; 7039 points[q*2+1] = points[p+1]; 7040 ++q; 7041 } 7042 } 7043 numPoints = q; 7044 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 7045 PetscInt fdof; 7046 7047 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7048 for (f = 0; f < numFields; ++f) { 7049 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7050 offsets[f+1] += fdof; 7051 } 7052 numIndices += dof; 7053 } 7054 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 7055 7056 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 7057 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 7058 if (numFields) { 7059 for (p = 0; p < numPoints*2; p += 2) { 7060 PetscInt o = points[p+1]; 7061 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 7062 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 7063 } 7064 } else { 7065 for (p = 0, off = 0; p < numPoints*2; p += 2) { 7066 PetscInt o = points[p+1]; 7067 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 7068 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 7069 } 7070 } 7071 if (useGlobalDefault && !useDefault) { 7072 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7073 } 7074 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 7075 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7076 if (ierr) { 7077 PetscMPIInt rank; 7078 PetscErrorCode ierr2; 7079 7080 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 7081 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7082 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 7083 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 7084 CHKERRQ(ierr); 7085 } 7086 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7087 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 7088 PetscFunctionReturn(0); 7089 } 7090 7091 #undef __FUNCT__ 7092 #define __FUNCT__ "DMPlexGetHybridBounds" 7093 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 7094 { 7095 DM_Plex *mesh = (DM_Plex*) dm->data; 7096 PetscInt dim; 7097 PetscErrorCode ierr; 7098 7099 PetscFunctionBegin; 7100 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7101 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7102 if (cMax) *cMax = mesh->hybridPointMax[dim]; 7103 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 7104 if (eMax) *eMax = mesh->hybridPointMax[1]; 7105 if (vMax) *vMax = mesh->hybridPointMax[0]; 7106 PetscFunctionReturn(0); 7107 } 7108 7109 #undef __FUNCT__ 7110 #define __FUNCT__ "DMPlexSetHybridBounds" 7111 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 7112 { 7113 DM_Plex *mesh = (DM_Plex*) dm->data; 7114 PetscInt dim; 7115 PetscErrorCode ierr; 7116 7117 PetscFunctionBegin; 7118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7119 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7120 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 7121 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 7122 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 7123 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 7124 PetscFunctionReturn(0); 7125 } 7126 7127 #undef __FUNCT__ 7128 #define __FUNCT__ "DMPlexGetVTKCellHeight" 7129 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7130 { 7131 DM_Plex *mesh = (DM_Plex*) dm->data; 7132 7133 PetscFunctionBegin; 7134 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7135 PetscValidPointer(cellHeight, 2); 7136 *cellHeight = mesh->vtkCellHeight; 7137 PetscFunctionReturn(0); 7138 } 7139 7140 #undef __FUNCT__ 7141 #define __FUNCT__ "DMPlexSetVTKCellHeight" 7142 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7143 { 7144 DM_Plex *mesh = (DM_Plex*) dm->data; 7145 7146 PetscFunctionBegin; 7147 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7148 mesh->vtkCellHeight = cellHeight; 7149 PetscFunctionReturn(0); 7150 } 7151 7152 #undef __FUNCT__ 7153 #define __FUNCT__ "DMPlexCreateNumbering_Private" 7154 /* We can easily have a form that takes an IS instead */ 7155 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 7156 { 7157 PetscSection section, globalSection; 7158 PetscInt *numbers, p; 7159 PetscErrorCode ierr; 7160 7161 PetscFunctionBegin; 7162 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7163 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7164 for (p = pStart; p < pEnd; ++p) { 7165 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7166 } 7167 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7168 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7169 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 7170 for (p = pStart; p < pEnd; ++p) { 7171 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7172 } 7173 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7174 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7175 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7176 PetscFunctionReturn(0); 7177 } 7178 7179 #undef __FUNCT__ 7180 #define __FUNCT__ "DMPlexGetCellNumbering" 7181 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7182 { 7183 DM_Plex *mesh = (DM_Plex*) dm->data; 7184 PetscInt cellHeight, cStart, cEnd, cMax; 7185 PetscErrorCode ierr; 7186 7187 PetscFunctionBegin; 7188 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7189 if (!mesh->globalCellNumbers) { 7190 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7191 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 7192 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7193 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7194 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 7195 } 7196 *globalCellNumbers = mesh->globalCellNumbers; 7197 PetscFunctionReturn(0); 7198 } 7199 7200 #undef __FUNCT__ 7201 #define __FUNCT__ "DMPlexGetVertexNumbering" 7202 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7203 { 7204 DM_Plex *mesh = (DM_Plex*) dm->data; 7205 PetscInt vStart, vEnd, vMax; 7206 PetscErrorCode ierr; 7207 7208 PetscFunctionBegin; 7209 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7210 if (!mesh->globalVertexNumbers) { 7211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7212 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 7213 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 7214 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 7215 } 7216 *globalVertexNumbers = mesh->globalVertexNumbers; 7217 PetscFunctionReturn(0); 7218 } 7219 7220 7221 #undef __FUNCT__ 7222 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 7223 /*@C 7224 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 7225 the local section and an SF describing the section point overlap. 7226 7227 Input Parameters: 7228 + s - The PetscSection for the local field layout 7229 . sf - The SF describing parallel layout of the section points 7230 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 7231 . label - The label specifying the points 7232 - labelValue - The label stratum specifying the points 7233 7234 Output Parameter: 7235 . gsection - The PetscSection for the global field layout 7236 7237 Note: This gives negative sizes and offsets to points not owned by this process 7238 7239 Level: developer 7240 7241 .seealso: PetscSectionCreate() 7242 @*/ 7243 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 7244 { 7245 PetscInt *neg; 7246 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 7247 PetscErrorCode ierr; 7248 7249 PetscFunctionBegin; 7250 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 7251 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 7252 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 7253 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 7254 /* Mark ghost points with negative dof */ 7255 for (p = pStart; p < pEnd; ++p) { 7256 PetscInt value; 7257 7258 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 7259 if (value != labelValue) continue; 7260 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 7261 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 7262 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 7263 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 7264 neg[p-pStart] = -(dof+1); 7265 } 7266 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 7267 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 7268 if (nroots >= 0) { 7269 if (nroots > pEnd - pStart) { 7270 PetscInt *tmpDof; 7271 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 7272 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 7273 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 7274 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 7275 for (p = pStart; p < pEnd; ++p) { 7276 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 7277 } 7278 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 7279 } else { 7280 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 7281 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 7282 } 7283 } 7284 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 7285 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7286 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 7287 7288 (*gsection)->atlasOff[p] = off; 7289 7290 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 7291 } 7292 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 7293 globalOff -= off; 7294 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7295 (*gsection)->atlasOff[p] += globalOff; 7296 7297 neg[p] = -((*gsection)->atlasOff[p]+1); 7298 } 7299 /* Put in negative offsets for ghost points */ 7300 if (nroots >= 0) { 7301 if (nroots > pEnd - pStart) { 7302 PetscInt *tmpOff; 7303 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 7304 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 7305 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 7306 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 7307 for (p = pStart; p < pEnd; ++p) { 7308 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 7309 } 7310 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 7311 } else { 7312 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 7313 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 7314 } 7315 } 7316 ierr = PetscFree(neg);CHKERRQ(ierr); 7317 PetscFunctionReturn(0); 7318 } 7319