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