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