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