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