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 PETSC_UNUSED 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 int *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 double *meshCoords = out.pointlist; 3394 int *cells = out.tetrahedronlist; 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 double *meshCoords = out.pointlist; 3514 int *cells = out.tetrahedronlist; 3515 3516 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3517 3518 ierr = DMPlexInvertCells_Internal(numCells, numCorners, cells);CHKERRQ(ierr); 3519 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3520 /* Set labels */ 3521 for (v = 0; v < numVertices; ++v) { 3522 if (out.pointmarkerlist[v]) { 3523 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3524 } 3525 } 3526 if (interpolate) { 3527 PetscInt e, f; 3528 3529 for (e = 0; e < out.numberofedges; e++) { 3530 if (out.edgemarkerlist[e]) { 3531 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3532 const PetscInt *edges; 3533 PetscInt numEdges; 3534 3535 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3536 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3537 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3538 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3539 } 3540 } 3541 for (f = 0; f < out.numberoftrifaces; f++) { 3542 if (out.trifacemarkerlist[f]) { 3543 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 3544 const PetscInt *faces; 3545 PetscInt numFaces; 3546 3547 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3548 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3549 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 3550 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3551 } 3552 } 3553 } 3554 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3555 } 3556 PetscFunctionReturn(0); 3557 } 3558 #endif 3559 3560 #if defined(PETSC_HAVE_CTETGEN) 3561 #include "ctetgen.h" 3562 3563 #undef __FUNCT__ 3564 #define __FUNCT__ "DMPlexGenerate_CTetgen" 3565 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 3566 { 3567 MPI_Comm comm; 3568 const PetscInt dim = 3; 3569 PLC *in, *out; 3570 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 3571 PetscMPIInt rank; 3572 PetscErrorCode ierr; 3573 3574 PetscFunctionBegin; 3575 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3576 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3577 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3578 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3579 ierr = PLCCreate(&in);CHKERRQ(ierr); 3580 ierr = PLCCreate(&out);CHKERRQ(ierr); 3581 3582 in->numberofpoints = vEnd - vStart; 3583 if (in->numberofpoints > 0) { 3584 PetscSection coordSection; 3585 Vec coordinates; 3586 PetscScalar *array; 3587 3588 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 3589 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 3590 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3591 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3592 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3593 for (v = vStart; v < vEnd; ++v) { 3594 const PetscInt idx = v - vStart; 3595 PetscInt off, d, m; 3596 3597 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3598 for (d = 0; d < dim; ++d) { 3599 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3600 } 3601 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 3602 3603 in->pointmarkerlist[idx] = (int) m; 3604 } 3605 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3606 } 3607 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 3608 3609 in->numberoffacets = fEnd - fStart; 3610 if (in->numberoffacets > 0) { 3611 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 3612 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 3613 for (f = fStart; f < fEnd; ++f) { 3614 const PetscInt idx = f - fStart; 3615 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 3616 polygon *poly; 3617 3618 in->facetlist[idx].numberofpolygons = 1; 3619 3620 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 3621 3622 in->facetlist[idx].numberofholes = 0; 3623 in->facetlist[idx].holelist = NULL; 3624 3625 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3626 for (p = 0; p < numPoints*2; p += 2) { 3627 const PetscInt point = points[p]; 3628 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 3629 } 3630 3631 poly = in->facetlist[idx].polygonlist; 3632 poly->numberofvertices = numVertices; 3633 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 3634 for (v = 0; v < numVertices; ++v) { 3635 const PetscInt vIdx = points[v] - vStart; 3636 poly->vertexlist[v] = vIdx; 3637 } 3638 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 3639 in->facetmarkerlist[idx] = (int) m; 3640 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3641 } 3642 } 3643 if (!rank) { 3644 TetGenOpts t; 3645 3646 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3647 t.in = boundary; /* Should go away */ 3648 t.plc = 1; 3649 t.quality = 1; 3650 t.edgesout = 1; 3651 t.zeroindex = 1; 3652 t.quiet = 1; 3653 t.verbose = verbose; 3654 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3655 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3656 } 3657 { 3658 const PetscInt numCorners = 4; 3659 const PetscInt numCells = out->numberoftetrahedra; 3660 const PetscInt numVertices = out->numberofpoints; 3661 const double *meshCoords = out->pointlist; 3662 int *cells = out->tetrahedronlist; 3663 3664 ierr = DMPlexInvertCells_Internal(numCells, numCorners, cells);CHKERRQ(ierr); 3665 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3666 /* Set labels */ 3667 for (v = 0; v < numVertices; ++v) { 3668 if (out->pointmarkerlist[v]) { 3669 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 3670 } 3671 } 3672 if (interpolate) { 3673 PetscInt e; 3674 3675 for (e = 0; e < out->numberofedges; e++) { 3676 if (out->edgemarkerlist[e]) { 3677 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 3678 const PetscInt *edges; 3679 PetscInt numEdges; 3680 3681 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3682 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3683 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 3684 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3685 } 3686 } 3687 for (f = 0; f < out->numberoftrifaces; f++) { 3688 if (out->trifacemarkerlist[f]) { 3689 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 3690 const PetscInt *faces; 3691 PetscInt numFaces; 3692 3693 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3694 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3695 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 3696 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3697 } 3698 } 3699 } 3700 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3701 } 3702 3703 ierr = PLCDestroy(&in);CHKERRQ(ierr); 3704 ierr = PLCDestroy(&out);CHKERRQ(ierr); 3705 PetscFunctionReturn(0); 3706 } 3707 3708 #undef __FUNCT__ 3709 #define __FUNCT__ "DMPlexRefine_CTetgen" 3710 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 3711 { 3712 MPI_Comm comm; 3713 const PetscInt dim = 3; 3714 PLC *in, *out; 3715 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3716 PetscMPIInt rank; 3717 PetscErrorCode ierr; 3718 3719 PetscFunctionBegin; 3720 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3721 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3722 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3723 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3724 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3725 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3726 ierr = PLCCreate(&in);CHKERRQ(ierr); 3727 ierr = PLCCreate(&out);CHKERRQ(ierr); 3728 3729 in->numberofpoints = vEnd - vStart; 3730 if (in->numberofpoints > 0) { 3731 PetscSection coordSection; 3732 Vec coordinates; 3733 PetscScalar *array; 3734 3735 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 3736 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 3737 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3738 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3739 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3740 for (v = vStart; v < vEnd; ++v) { 3741 const PetscInt idx = v - vStart; 3742 PetscInt off, d, m; 3743 3744 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3745 for (d = 0; d < dim; ++d) { 3746 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3747 } 3748 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 3749 3750 in->pointmarkerlist[idx] = (int) m; 3751 } 3752 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3753 } 3754 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3755 3756 in->numberofcorners = 4; 3757 in->numberoftetrahedra = cEnd - cStart; 3758 in->tetrahedronvolumelist = maxVolumes; 3759 if (in->numberoftetrahedra > 0) { 3760 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 3761 for (c = cStart; c < cEnd; ++c) { 3762 const PetscInt idx = c - cStart; 3763 PetscInt *closure = NULL; 3764 PetscInt closureSize; 3765 3766 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3767 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 3768 for (v = 0; v < 4; ++v) { 3769 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 3770 } 3771 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3772 } 3773 } 3774 if (!rank) { 3775 TetGenOpts t; 3776 3777 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3778 3779 t.in = dm; /* Should go away */ 3780 t.refine = 1; 3781 t.varvolume = 1; 3782 t.quality = 1; 3783 t.edgesout = 1; 3784 t.zeroindex = 1; 3785 t.quiet = 1; 3786 t.verbose = verbose; /* Change this */ 3787 3788 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3789 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3790 } 3791 { 3792 const PetscInt numCorners = 4; 3793 const PetscInt numCells = out->numberoftetrahedra; 3794 const PetscInt numVertices = out->numberofpoints; 3795 const double *meshCoords = out->pointlist; 3796 int *cells = out->tetrahedronlist; 3797 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3798 3799 ierr = DMPlexInvertCells_Internal(numCells, numCorners, cells);CHKERRQ(ierr); 3800 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3801 /* Set labels */ 3802 for (v = 0; v < numVertices; ++v) { 3803 if (out->pointmarkerlist[v]) { 3804 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 3805 } 3806 } 3807 if (interpolate) { 3808 PetscInt e, f; 3809 3810 for (e = 0; e < out->numberofedges; e++) { 3811 if (out->edgemarkerlist[e]) { 3812 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 3813 const PetscInt *edges; 3814 PetscInt numEdges; 3815 3816 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3817 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3818 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 3819 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3820 } 3821 } 3822 for (f = 0; f < out->numberoftrifaces; f++) { 3823 if (out->trifacemarkerlist[f]) { 3824 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 3825 const PetscInt *faces; 3826 PetscInt numFaces; 3827 3828 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3829 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3830 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 3831 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3832 } 3833 } 3834 } 3835 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3836 } 3837 ierr = PLCDestroy(&in);CHKERRQ(ierr); 3838 ierr = PLCDestroy(&out);CHKERRQ(ierr); 3839 PetscFunctionReturn(0); 3840 } 3841 #endif 3842 3843 #undef __FUNCT__ 3844 #define __FUNCT__ "DMPlexGenerate" 3845 /*@C 3846 DMPlexGenerate - Generates a mesh. 3847 3848 Not Collective 3849 3850 Input Parameters: 3851 + boundary - The DMPlex boundary object 3852 . name - The mesh generation package name 3853 - interpolate - Flag to create intermediate mesh elements 3854 3855 Output Parameter: 3856 . mesh - The DMPlex object 3857 3858 Level: intermediate 3859 3860 .keywords: mesh, elements 3861 .seealso: DMPlexCreate(), DMRefine() 3862 @*/ 3863 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 3864 { 3865 PetscInt dim; 3866 char genname[1024]; 3867 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 3868 PetscErrorCode ierr; 3869 3870 PetscFunctionBegin; 3871 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 3872 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 3873 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 3874 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 3875 if (flg) name = genname; 3876 if (name) { 3877 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 3878 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 3879 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 3880 } 3881 switch (dim) { 3882 case 1: 3883 if (!name || isTriangle) { 3884 #if defined(PETSC_HAVE_TRIANGLE) 3885 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 3886 #else 3887 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 3888 #endif 3889 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 3890 break; 3891 case 2: 3892 if (!name || isCTetgen) { 3893 #if defined(PETSC_HAVE_CTETGEN) 3894 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 3895 #else 3896 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 3897 #endif 3898 } else if (isTetgen) { 3899 #if defined(PETSC_HAVE_TETGEN) 3900 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 3901 #else 3902 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 3903 #endif 3904 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 3905 break; 3906 default: 3907 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 3908 } 3909 PetscFunctionReturn(0); 3910 } 3911 3912 typedef PetscInt CellRefiner; 3913 3914 #undef __FUNCT__ 3915 #define __FUNCT__ "GetDepthStart_Private" 3916 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 3917 { 3918 PetscFunctionBegin; 3919 if (cStart) *cStart = 0; 3920 if (vStart) *vStart = depthSize[depth]; 3921 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 3922 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 3923 PetscFunctionReturn(0); 3924 } 3925 3926 #undef __FUNCT__ 3927 #define __FUNCT__ "GetDepthEnd_Private" 3928 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 3929 { 3930 PetscFunctionBegin; 3931 if (cEnd) *cEnd = depthSize[depth]; 3932 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 3933 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 3934 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 3935 PetscFunctionReturn(0); 3936 } 3937 3938 #undef __FUNCT__ 3939 #define __FUNCT__ "CellRefinerGetSizes" 3940 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 3941 { 3942 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 3943 PetscErrorCode ierr; 3944 3945 PetscFunctionBegin; 3946 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3947 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 3948 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3949 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 3950 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 3951 switch (refiner) { 3952 case 1: 3953 /* Simplicial 2D */ 3954 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 3955 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 3956 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 3957 break; 3958 case 3: 3959 /* Hybrid 2D */ 3960 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 3961 cMax = PetscMin(cEnd, cMax); 3962 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 3963 fMax = PetscMin(fEnd, fMax); 3964 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 3965 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 */ 3966 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 3967 break; 3968 case 2: 3969 /* Hex 2D */ 3970 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 3971 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 3972 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 3973 break; 3974 default: 3975 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 3976 } 3977 PetscFunctionReturn(0); 3978 } 3979 3980 #undef __FUNCT__ 3981 #define __FUNCT__ "CellRefinerSetConeSizes" 3982 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 3983 { 3984 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 3985 PetscErrorCode ierr; 3986 3987 PetscFunctionBegin; 3988 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3989 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3990 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 3991 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3992 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 3993 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 3994 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 3995 switch (refiner) { 3996 case 1: 3997 /* Simplicial 2D */ 3998 /* All cells have 3 faces */ 3999 for (c = cStart; c < cEnd; ++c) { 4000 for (r = 0; r < 4; ++r) { 4001 const PetscInt newp = (c - cStart)*4 + r; 4002 4003 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 4004 } 4005 } 4006 /* Split faces have 2 vertices and the same cells as the parent */ 4007 for (f = fStart; f < fEnd; ++f) { 4008 for (r = 0; r < 2; ++r) { 4009 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4010 PetscInt size; 4011 4012 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4013 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4014 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4015 } 4016 } 4017 /* Interior faces have 2 vertices and 2 cells */ 4018 for (c = cStart; c < cEnd; ++c) { 4019 for (r = 0; r < 3; ++r) { 4020 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 4021 4022 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4023 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4024 } 4025 } 4026 /* Old vertices have identical supports */ 4027 for (v = vStart; v < vEnd; ++v) { 4028 const PetscInt newp = vStartNew + (v - vStart); 4029 PetscInt size; 4030 4031 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4032 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4033 } 4034 /* Face vertices have 2 + cells*2 supports */ 4035 for (f = fStart; f < fEnd; ++f) { 4036 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4037 PetscInt size; 4038 4039 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4040 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 4041 } 4042 break; 4043 case 2: 4044 /* Hex 2D */ 4045 /* All cells have 4 faces */ 4046 for (c = cStart; c < cEnd; ++c) { 4047 for (r = 0; r < 4; ++r) { 4048 const PetscInt newp = (c - cStart)*4 + r; 4049 4050 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 4051 } 4052 } 4053 /* Split faces have 2 vertices and the same cells as the parent */ 4054 for (f = fStart; f < fEnd; ++f) { 4055 for (r = 0; r < 2; ++r) { 4056 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4057 PetscInt size; 4058 4059 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4060 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4061 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4062 } 4063 } 4064 /* Interior faces have 2 vertices and 2 cells */ 4065 for (c = cStart; c < cEnd; ++c) { 4066 for (r = 0; r < 4; ++r) { 4067 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4068 4069 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4070 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4071 } 4072 } 4073 /* Old vertices have identical supports */ 4074 for (v = vStart; v < vEnd; ++v) { 4075 const PetscInt newp = vStartNew + (v - vStart); 4076 PetscInt size; 4077 4078 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4079 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4080 } 4081 /* Face vertices have 2 + cells supports */ 4082 for (f = fStart; f < fEnd; ++f) { 4083 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4084 PetscInt size; 4085 4086 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4087 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 4088 } 4089 /* Cell vertices have 4 supports */ 4090 for (c = cStart; c < cEnd; ++c) { 4091 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4092 4093 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 4094 } 4095 break; 4096 case 3: 4097 /* Hybrid 2D */ 4098 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4099 cMax = PetscMin(cEnd, cMax); 4100 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4101 fMax = PetscMin(fEnd, fMax); 4102 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 4103 /* Interior cells have 3 faces */ 4104 for (c = cStart; c < cMax; ++c) { 4105 for (r = 0; r < 4; ++r) { 4106 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 4107 4108 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 4109 } 4110 } 4111 /* Hybrid cells have 4 faces */ 4112 for (c = cMax; c < cEnd; ++c) { 4113 for (r = 0; r < 2; ++r) { 4114 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 4115 4116 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 4117 } 4118 } 4119 /* Interior split faces have 2 vertices and the same cells as the parent */ 4120 for (f = fStart; f < fMax; ++f) { 4121 for (r = 0; r < 2; ++r) { 4122 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4123 PetscInt size; 4124 4125 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4126 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4127 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4128 } 4129 } 4130 /* Interior cell faces have 2 vertices and 2 cells */ 4131 for (c = cStart; c < cMax; ++c) { 4132 for (r = 0; r < 3; ++r) { 4133 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 4134 4135 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4136 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4137 } 4138 } 4139 /* Hybrid faces have 2 vertices and the same cells */ 4140 for (f = fMax; f < fEnd; ++f) { 4141 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 4142 PetscInt size; 4143 4144 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4145 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4146 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4147 } 4148 /* Hybrid cell faces have 2 vertices and 2 cells */ 4149 for (c = cMax; c < cEnd; ++c) { 4150 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4151 4152 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 4153 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 4154 } 4155 /* Old vertices have identical supports */ 4156 for (v = vStart; v < vEnd; ++v) { 4157 const PetscInt newp = vStartNew + (v - vStart); 4158 PetscInt size; 4159 4160 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4161 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 4162 } 4163 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 4164 for (f = fStart; f < fMax; ++f) { 4165 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4166 const PetscInt *support; 4167 PetscInt size, newSize = 2, s; 4168 4169 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4170 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4171 for (s = 0; s < size; ++s) { 4172 if (support[s] >= cMax) newSize += 1; 4173 else newSize += 2; 4174 } 4175 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 4176 } 4177 break; 4178 default: 4179 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 4180 } 4181 PetscFunctionReturn(0); 4182 } 4183 4184 #undef __FUNCT__ 4185 #define __FUNCT__ "CellRefinerSetCones" 4186 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 4187 { 4188 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; 4189 PetscInt maxSupportSize, *supportRef; 4190 PetscErrorCode ierr; 4191 4192 PetscFunctionBegin; 4193 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4194 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4195 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 4196 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4197 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4198 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 4199 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 4200 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 4201 switch (refiner) { 4202 case 1: 4203 /* Simplicial 2D */ 4204 /* 4205 2 4206 |\ 4207 | \ 4208 | \ 4209 | \ 4210 | C \ 4211 | \ 4212 | \ 4213 2---1---1 4214 |\ D / \ 4215 | 2 0 \ 4216 |A \ / B \ 4217 0---0-------1 4218 */ 4219 /* All cells have 3 faces */ 4220 for (c = cStart; c < cEnd; ++c) { 4221 const PetscInt newp = cStartNew + (c - cStart)*4; 4222 const PetscInt *cone, *ornt; 4223 PetscInt coneNew[3], orntNew[3]; 4224 4225 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4226 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4227 /* A triangle */ 4228 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4229 orntNew[0] = ornt[0]; 4230 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 4231 orntNew[1] = -2; 4232 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4233 orntNew[2] = ornt[2]; 4234 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4235 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4236 #if 1 4237 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); 4238 for (p = 0; p < 3; ++p) { 4239 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); 4240 } 4241 #endif 4242 /* B triangle */ 4243 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4244 orntNew[0] = ornt[0]; 4245 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4246 orntNew[1] = ornt[1]; 4247 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 4248 orntNew[2] = -2; 4249 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4250 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4251 #if 1 4252 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); 4253 for (p = 0; p < 3; ++p) { 4254 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); 4255 } 4256 #endif 4257 /* C triangle */ 4258 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 4259 orntNew[0] = -2; 4260 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4261 orntNew[1] = ornt[1]; 4262 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4263 orntNew[2] = ornt[2]; 4264 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4265 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4266 #if 1 4267 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); 4268 for (p = 0; p < 3; ++p) { 4269 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); 4270 } 4271 #endif 4272 /* D triangle */ 4273 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 4274 orntNew[0] = 0; 4275 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 4276 orntNew[1] = 0; 4277 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 4278 orntNew[2] = 0; 4279 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4280 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4281 #if 1 4282 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); 4283 for (p = 0; p < 3; ++p) { 4284 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); 4285 } 4286 #endif 4287 } 4288 /* Split faces have 2 vertices and the same cells as the parent */ 4289 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4290 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4291 for (f = fStart; f < fEnd; ++f) { 4292 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4293 4294 for (r = 0; r < 2; ++r) { 4295 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4296 const PetscInt *cone, *support; 4297 PetscInt coneNew[2], coneSize, c, supportSize, s; 4298 4299 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4300 coneNew[0] = vStartNew + (cone[0] - vStart); 4301 coneNew[1] = vStartNew + (cone[1] - vStart); 4302 coneNew[(r+1)%2] = newv; 4303 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4304 #if 1 4305 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4306 for (p = 0; p < 2; ++p) { 4307 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); 4308 } 4309 #endif 4310 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4311 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4312 for (s = 0; s < supportSize; ++s) { 4313 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4314 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4315 for (c = 0; c < coneSize; ++c) { 4316 if (cone[c] == f) break; 4317 } 4318 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 4319 } 4320 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4321 #if 1 4322 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4323 for (p = 0; p < supportSize; ++p) { 4324 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); 4325 } 4326 #endif 4327 } 4328 } 4329 /* Interior faces have 2 vertices and 2 cells */ 4330 for (c = cStart; c < cEnd; ++c) { 4331 const PetscInt *cone; 4332 4333 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4334 for (r = 0; r < 3; ++r) { 4335 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 4336 PetscInt coneNew[2]; 4337 PetscInt supportNew[2]; 4338 4339 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4340 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 4341 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4342 #if 1 4343 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4344 for (p = 0; p < 2; ++p) { 4345 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); 4346 } 4347 #endif 4348 supportNew[0] = (c - cStart)*4 + (r+1)%3; 4349 supportNew[1] = (c - cStart)*4 + 3; 4350 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4351 #if 1 4352 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4353 for (p = 0; p < 2; ++p) { 4354 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); 4355 } 4356 #endif 4357 } 4358 } 4359 /* Old vertices have identical supports */ 4360 for (v = vStart; v < vEnd; ++v) { 4361 const PetscInt newp = vStartNew + (v - vStart); 4362 const PetscInt *support, *cone; 4363 PetscInt size, s; 4364 4365 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4366 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 4367 for (s = 0; s < size; ++s) { 4368 PetscInt r = 0; 4369 4370 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4371 if (cone[1] == v) r = 1; 4372 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 4373 } 4374 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4375 #if 1 4376 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4377 for (p = 0; p < size; ++p) { 4378 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); 4379 } 4380 #endif 4381 } 4382 /* Face vertices have 2 + cells*2 supports */ 4383 for (f = fStart; f < fEnd; ++f) { 4384 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4385 const PetscInt *cone, *support; 4386 PetscInt size, s; 4387 4388 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4389 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4390 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 4391 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 4392 for (s = 0; s < size; ++s) { 4393 PetscInt r = 0; 4394 4395 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4396 if (cone[1] == f) r = 1; 4397 else if (cone[2] == f) r = 2; 4398 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 4399 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 4400 } 4401 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4402 #if 1 4403 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4404 for (p = 0; p < 2+size*2; ++p) { 4405 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); 4406 } 4407 #endif 4408 } 4409 ierr = PetscFree(supportRef);CHKERRQ(ierr); 4410 break; 4411 case 2: 4412 /* Hex 2D */ 4413 /* 4414 3---------2---------2 4415 | | | 4416 | D 2 C | 4417 | | | 4418 3----3----0----1----1 4419 | | | 4420 | A 0 B | 4421 | | | 4422 0---------0---------1 4423 */ 4424 /* All cells have 4 faces */ 4425 for (c = cStart; c < cEnd; ++c) { 4426 const PetscInt newp = (c - cStart)*4; 4427 const PetscInt *cone, *ornt; 4428 PetscInt coneNew[4], orntNew[4]; 4429 4430 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4431 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4432 /* A quad */ 4433 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4434 orntNew[0] = ornt[0]; 4435 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 4436 orntNew[1] = 0; 4437 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 4438 orntNew[2] = -2; 4439 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 4440 orntNew[3] = ornt[3]; 4441 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4442 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4443 #if 1 4444 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); 4445 for (p = 0; p < 4; ++p) { 4446 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); 4447 } 4448 #endif 4449 /* B quad */ 4450 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4451 orntNew[0] = ornt[0]; 4452 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4453 orntNew[1] = ornt[1]; 4454 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 4455 orntNew[2] = 0; 4456 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 4457 orntNew[3] = -2; 4458 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4459 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4460 #if 1 4461 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); 4462 for (p = 0; p < 4; ++p) { 4463 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); 4464 } 4465 #endif 4466 /* C quad */ 4467 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 4468 orntNew[0] = -2; 4469 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4470 orntNew[1] = ornt[1]; 4471 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4472 orntNew[2] = ornt[2]; 4473 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 4474 orntNew[3] = 0; 4475 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4476 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4477 #if 1 4478 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); 4479 for (p = 0; p < 4; ++p) { 4480 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); 4481 } 4482 #endif 4483 /* D quad */ 4484 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 4485 orntNew[0] = 0; 4486 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 4487 orntNew[1] = -2; 4488 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4489 orntNew[2] = ornt[2]; 4490 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 4491 orntNew[3] = ornt[3]; 4492 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4493 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4494 #if 1 4495 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); 4496 for (p = 0; p < 4; ++p) { 4497 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); 4498 } 4499 #endif 4500 } 4501 /* Split faces have 2 vertices and the same cells as the parent */ 4502 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4503 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4504 for (f = fStart; f < fEnd; ++f) { 4505 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4506 4507 for (r = 0; r < 2; ++r) { 4508 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4509 const PetscInt *cone, *support; 4510 PetscInt coneNew[2], coneSize, c, supportSize, s; 4511 4512 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4513 coneNew[0] = vStartNew + (cone[0] - vStart); 4514 coneNew[1] = vStartNew + (cone[1] - vStart); 4515 coneNew[(r+1)%2] = newv; 4516 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4517 #if 1 4518 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4519 for (p = 0; p < 2; ++p) { 4520 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); 4521 } 4522 #endif 4523 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4524 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4525 for (s = 0; s < supportSize; ++s) { 4526 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4527 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4528 for (c = 0; c < coneSize; ++c) { 4529 if (cone[c] == f) break; 4530 } 4531 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 4532 } 4533 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4534 #if 1 4535 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4536 for (p = 0; p < supportSize; ++p) { 4537 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); 4538 } 4539 #endif 4540 } 4541 } 4542 /* Interior faces have 2 vertices and 2 cells */ 4543 for (c = cStart; c < cEnd; ++c) { 4544 const PetscInt *cone; 4545 PetscInt coneNew[2], supportNew[2]; 4546 4547 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4548 for (r = 0; r < 4; ++r) { 4549 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4550 4551 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4552 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4553 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4554 #if 1 4555 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4556 for (p = 0; p < 2; ++p) { 4557 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); 4558 } 4559 #endif 4560 supportNew[0] = (c - cStart)*4 + r; 4561 supportNew[1] = (c - cStart)*4 + (r+1)%4; 4562 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4563 #if 1 4564 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4565 for (p = 0; p < 2; ++p) { 4566 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); 4567 } 4568 #endif 4569 } 4570 } 4571 /* Old vertices have identical supports */ 4572 for (v = vStart; v < vEnd; ++v) { 4573 const PetscInt newp = vStartNew + (v - vStart); 4574 const PetscInt *support, *cone; 4575 PetscInt size, s; 4576 4577 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4578 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 4579 for (s = 0; s < size; ++s) { 4580 PetscInt r = 0; 4581 4582 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4583 if (cone[1] == v) r = 1; 4584 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 4585 } 4586 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4587 #if 1 4588 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4589 for (p = 0; p < size; ++p) { 4590 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); 4591 } 4592 #endif 4593 } 4594 /* Face vertices have 2 + cells supports */ 4595 for (f = fStart; f < fEnd; ++f) { 4596 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4597 const PetscInt *cone, *support; 4598 PetscInt size, s; 4599 4600 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4601 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4602 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 4603 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 4604 for (s = 0; s < size; ++s) { 4605 PetscInt r = 0; 4606 4607 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4608 if (cone[1] == f) r = 1; 4609 else if (cone[2] == f) r = 2; 4610 else if (cone[3] == f) r = 3; 4611 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 4612 } 4613 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4614 #if 1 4615 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4616 for (p = 0; p < 2+size; ++p) { 4617 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); 4618 } 4619 #endif 4620 } 4621 /* Cell vertices have 4 supports */ 4622 for (c = cStart; c < cEnd; ++c) { 4623 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 4624 PetscInt supportNew[4]; 4625 4626 for (r = 0; r < 4; ++r) { 4627 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 4628 } 4629 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4630 } 4631 break; 4632 case 3: 4633 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 4634 cMax = PetscMin(cEnd, cMax); 4635 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 4636 fMax = PetscMin(fEnd, fMax); 4637 /* Interior cells have 3 faces */ 4638 for (c = cStart; c < cMax; ++c) { 4639 const PetscInt newp = cStartNew + (c - cStart)*4; 4640 const PetscInt *cone, *ornt; 4641 PetscInt coneNew[3], orntNew[3]; 4642 4643 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4644 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4645 /* A triangle */ 4646 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4647 orntNew[0] = ornt[0]; 4648 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 4649 orntNew[1] = -2; 4650 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 4651 orntNew[2] = ornt[2]; 4652 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4653 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4654 #if 1 4655 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); 4656 for (p = 0; p < 3; ++p) { 4657 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); 4658 } 4659 #endif 4660 /* B triangle */ 4661 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4662 orntNew[0] = ornt[0]; 4663 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4664 orntNew[1] = ornt[1]; 4665 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 4666 orntNew[2] = -2; 4667 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4668 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4669 #if 1 4670 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); 4671 for (p = 0; p < 3; ++p) { 4672 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); 4673 } 4674 #endif 4675 /* C triangle */ 4676 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 4677 orntNew[0] = -2; 4678 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4679 orntNew[1] = ornt[1]; 4680 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 4681 orntNew[2] = ornt[2]; 4682 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 4683 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 4684 #if 1 4685 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); 4686 for (p = 0; p < 3; ++p) { 4687 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); 4688 } 4689 #endif 4690 /* D triangle */ 4691 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 4692 orntNew[0] = 0; 4693 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 4694 orntNew[1] = 0; 4695 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 4696 orntNew[2] = 0; 4697 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 4698 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 4699 #if 1 4700 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); 4701 for (p = 0; p < 3; ++p) { 4702 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); 4703 } 4704 #endif 4705 } 4706 /* 4707 2----3----3 4708 | | 4709 | B | 4710 | | 4711 0----4--- 1 4712 | | 4713 | A | 4714 | | 4715 0----2----1 4716 */ 4717 /* Hybrid cells have 4 faces */ 4718 for (c = cMax; c < cEnd; ++c) { 4719 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 4720 const PetscInt *cone, *ornt; 4721 PetscInt coneNew[4], orntNew[4]; 4722 4723 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4724 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 4725 /* A quad */ 4726 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 4727 orntNew[0] = ornt[0]; 4728 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 4729 orntNew[1] = ornt[1]; 4730 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 4731 orntNew[2] = 0; 4732 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4733 orntNew[3] = 0; 4734 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 4735 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 4736 #if 1 4737 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); 4738 for (p = 0; p < 4; ++p) { 4739 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); 4740 } 4741 #endif 4742 /* B quad */ 4743 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 4744 orntNew[0] = ornt[0]; 4745 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 4746 orntNew[1] = ornt[1]; 4747 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4748 orntNew[2] = 0; 4749 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 4750 orntNew[3] = 0; 4751 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 4752 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 4753 #if 1 4754 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); 4755 for (p = 0; p < 4; ++p) { 4756 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); 4757 } 4758 #endif 4759 } 4760 /* Interior split faces have 2 vertices and the same cells as the parent */ 4761 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 4762 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 4763 for (f = fStart; f < fMax; ++f) { 4764 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 4765 4766 for (r = 0; r < 2; ++r) { 4767 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 4768 const PetscInt *cone, *support; 4769 PetscInt coneNew[2], coneSize, c, supportSize, s; 4770 4771 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4772 coneNew[0] = vStartNew + (cone[0] - vStart); 4773 coneNew[1] = vStartNew + (cone[1] - vStart); 4774 coneNew[(r+1)%2] = newv; 4775 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4776 #if 1 4777 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4778 for (p = 0; p < 2; ++p) { 4779 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); 4780 } 4781 #endif 4782 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 4783 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4784 for (s = 0; s < supportSize; ++s) { 4785 if (support[s] >= cMax) { 4786 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 4787 } else { 4788 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4789 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4790 for (c = 0; c < coneSize; ++c) { 4791 if (cone[c] == f) break; 4792 } 4793 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 4794 } 4795 } 4796 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4797 #if 1 4798 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4799 for (p = 0; p < supportSize; ++p) { 4800 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); 4801 } 4802 #endif 4803 } 4804 } 4805 /* Interior cell faces have 2 vertices and 2 cells */ 4806 for (c = cStart; c < cMax; ++c) { 4807 const PetscInt *cone; 4808 4809 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4810 for (r = 0; r < 3; ++r) { 4811 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 4812 PetscInt coneNew[2]; 4813 PetscInt supportNew[2]; 4814 4815 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 4816 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 4817 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4818 #if 1 4819 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4820 for (p = 0; p < 2; ++p) { 4821 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); 4822 } 4823 #endif 4824 supportNew[0] = (c - cStart)*4 + (r+1)%3; 4825 supportNew[1] = (c - cStart)*4 + 3; 4826 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4827 #if 1 4828 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4829 for (p = 0; p < 2; ++p) { 4830 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); 4831 } 4832 #endif 4833 } 4834 } 4835 /* Interior hybrid faces have 2 vertices and the same cells */ 4836 for (f = fMax; f < fEnd; ++f) { 4837 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 4838 const PetscInt *cone; 4839 const PetscInt *support; 4840 PetscInt coneNew[2]; 4841 PetscInt supportNew[2]; 4842 PetscInt size, s, r; 4843 4844 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 4845 coneNew[0] = vStartNew + (cone[0] - vStart); 4846 coneNew[1] = vStartNew + (cone[1] - vStart); 4847 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4848 #if 1 4849 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4850 for (p = 0; p < 2; ++p) { 4851 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); 4852 } 4853 #endif 4854 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4855 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4856 for (s = 0; s < size; ++s) { 4857 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4858 for (r = 0; r < 2; ++r) { 4859 if (cone[r+2] == f) break; 4860 } 4861 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 4862 } 4863 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4864 #if 1 4865 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4866 for (p = 0; p < size; ++p) { 4867 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); 4868 } 4869 #endif 4870 } 4871 /* Cell hybrid faces have 2 vertices and 2 cells */ 4872 for (c = cMax; c < cEnd; ++c) { 4873 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 4874 const PetscInt *cone; 4875 PetscInt coneNew[2]; 4876 PetscInt supportNew[2]; 4877 4878 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 4879 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 4880 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 4881 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 4882 #if 1 4883 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4884 for (p = 0; p < 2; ++p) { 4885 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); 4886 } 4887 #endif 4888 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 4889 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 4890 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 4891 #if 1 4892 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 4893 for (p = 0; p < 2; ++p) { 4894 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); 4895 } 4896 #endif 4897 } 4898 /* Old vertices have identical supports */ 4899 for (v = vStart; v < vEnd; ++v) { 4900 const PetscInt newp = vStartNew + (v - vStart); 4901 const PetscInt *support, *cone; 4902 PetscInt size, s; 4903 4904 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 4905 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 4906 for (s = 0; s < size; ++s) { 4907 if (support[s] >= fMax) { 4908 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 4909 } else { 4910 PetscInt r = 0; 4911 4912 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4913 if (cone[1] == v) r = 1; 4914 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 4915 } 4916 } 4917 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4918 #if 1 4919 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4920 for (p = 0; p < size; ++p) { 4921 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); 4922 } 4923 #endif 4924 } 4925 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 4926 for (f = fStart; f < fMax; ++f) { 4927 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 4928 const PetscInt *cone, *support; 4929 PetscInt size, newSize = 2, s; 4930 4931 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 4932 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4933 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 4934 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 4935 for (s = 0; s < size; ++s) { 4936 PetscInt r = 0; 4937 4938 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4939 if (support[s] >= cMax) { 4940 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 4941 4942 newSize += 1; 4943 } else { 4944 if (cone[1] == f) r = 1; 4945 else if (cone[2] == f) r = 2; 4946 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 4947 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 4948 4949 newSize += 2; 4950 } 4951 } 4952 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 4953 #if 1 4954 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 4955 for (p = 0; p < newSize; ++p) { 4956 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); 4957 } 4958 #endif 4959 } 4960 ierr = PetscFree(supportRef);CHKERRQ(ierr); 4961 break; 4962 default: 4963 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 4964 } 4965 PetscFunctionReturn(0); 4966 } 4967 4968 #undef __FUNCT__ 4969 #define __FUNCT__ "CellRefinerSetCoordinates" 4970 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 4971 { 4972 PetscSection coordSection, coordSectionNew; 4973 Vec coordinates, coordinatesNew; 4974 PetscScalar *coords, *coordsNew; 4975 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 4976 PetscErrorCode ierr; 4977 4978 PetscFunctionBegin; 4979 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4980 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4981 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4982 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4983 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 4984 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 4985 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 4986 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4987 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 4988 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 4989 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 4990 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 4991 if (fMax < 0) fMax = fEnd; 4992 switch (refiner) { 4993 case 1: 4994 case 2: 4995 case 3: 4996 /* Simplicial and Hex 2D */ 4997 /* All vertices have the dim coordinates */ 4998 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 4999 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 5000 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 5001 } 5002 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 5003 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 5004 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5005 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 5006 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 5007 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 5008 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 5009 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 5010 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 5011 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5012 /* Old vertices have the same coordinates */ 5013 for (v = vStart; v < vEnd; ++v) { 5014 const PetscInt newv = vStartNew + (v - vStart); 5015 PetscInt off, offnew, d; 5016 5017 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5018 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5019 for (d = 0; d < dim; ++d) { 5020 coordsNew[offnew+d] = coords[off+d]; 5021 } 5022 } 5023 /* Face vertices have the average of endpoint coordinates */ 5024 for (f = fStart; f < fMax; ++f) { 5025 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5026 const PetscInt *cone; 5027 PetscInt coneSize, offA, offB, offnew, d; 5028 5029 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 5030 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 5031 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5032 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5033 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5034 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5035 for (d = 0; d < dim; ++d) { 5036 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 5037 } 5038 } 5039 /* Just Hex 2D */ 5040 if (refiner == 2) { 5041 /* Cell vertices have the average of corner coordinates */ 5042 for (c = cStart; c < cEnd; ++c) { 5043 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5044 PetscInt *cone = NULL; 5045 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 5046 5047 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5048 for (p = 0; p < closureSize*2; p += 2) { 5049 const PetscInt point = cone[p]; 5050 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 5051 } 5052 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 5053 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5054 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5055 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 5056 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 5057 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5058 for (d = 0; d < dim; ++d) { 5059 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 5060 } 5061 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5062 } 5063 } 5064 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 5065 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5066 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 5067 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 5068 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 5069 break; 5070 default: 5071 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5072 } 5073 PetscFunctionReturn(0); 5074 } 5075 5076 #undef __FUNCT__ 5077 #define __FUNCT__ "DMPlexCreateProcessSF" 5078 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 5079 { 5080 PetscInt numRoots, numLeaves, l; 5081 const PetscInt *localPoints; 5082 const PetscSFNode *remotePoints; 5083 PetscInt *localPointsNew; 5084 PetscSFNode *remotePointsNew; 5085 PetscInt *ranks, *ranksNew; 5086 PetscErrorCode ierr; 5087 5088 PetscFunctionBegin; 5089 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5090 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 5091 for (l = 0; l < numLeaves; ++l) { 5092 ranks[l] = remotePoints[l].rank; 5093 } 5094 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 5095 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 5096 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 5097 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 5098 for (l = 0; l < numLeaves; ++l) { 5099 ranksNew[l] = ranks[l]; 5100 localPointsNew[l] = l; 5101 remotePointsNew[l].index = 0; 5102 remotePointsNew[l].rank = ranksNew[l]; 5103 } 5104 ierr = PetscFree(ranks);CHKERRQ(ierr); 5105 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 5106 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 5107 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 5108 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 5109 PetscFunctionReturn(0); 5110 } 5111 5112 #undef __FUNCT__ 5113 #define __FUNCT__ "CellRefinerCreateSF" 5114 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5115 { 5116 PetscSF sf, sfNew, sfProcess; 5117 IS processRanks; 5118 MPI_Datatype depthType; 5119 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 5120 const PetscInt *localPoints, *neighbors; 5121 const PetscSFNode *remotePoints; 5122 PetscInt *localPointsNew; 5123 PetscSFNode *remotePointsNew; 5124 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 5125 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 5126 PetscErrorCode ierr; 5127 5128 PetscFunctionBegin; 5129 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 5130 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5131 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5132 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5133 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5134 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5135 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5136 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5137 switch (refiner) { 5138 case 3: 5139 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5140 cMax = PetscMin(cEnd, cMax); 5141 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5142 fMax = PetscMin(fEnd, fMax); 5143 } 5144 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 5145 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 5146 /* Caculate size of new SF */ 5147 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5148 if (numRoots < 0) PetscFunctionReturn(0); 5149 for (l = 0; l < numLeaves; ++l) { 5150 const PetscInt p = localPoints[l]; 5151 5152 switch (refiner) { 5153 case 1: 5154 /* Simplicial 2D */ 5155 if ((p >= vStart) && (p < vEnd)) { 5156 /* Old vertices stay the same */ 5157 ++numLeavesNew; 5158 } else if ((p >= fStart) && (p < fEnd)) { 5159 /* Old faces add new faces and vertex */ 5160 numLeavesNew += 1 + 2; 5161 } else if ((p >= cStart) && (p < cEnd)) { 5162 /* Old cells add new cells and interior faces */ 5163 numLeavesNew += 4 + 3; 5164 } 5165 break; 5166 case 2: 5167 /* Hex 2D */ 5168 if ((p >= vStart) && (p < vEnd)) { 5169 /* Old vertices stay the same */ 5170 ++numLeavesNew; 5171 } else if ((p >= fStart) && (p < fEnd)) { 5172 /* Old faces add new faces and vertex */ 5173 numLeavesNew += 1 + 2; 5174 } else if ((p >= cStart) && (p < cEnd)) { 5175 /* Old cells add new cells and interior faces */ 5176 numLeavesNew += 4 + 4; 5177 } 5178 break; 5179 default: 5180 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5181 } 5182 } 5183 /* Communicate depthSizes for each remote rank */ 5184 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 5185 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 5186 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 5187 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); 5188 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 5189 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 5190 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 5191 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 5192 for (n = 0; n < numNeighbors; ++n) { 5193 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 5194 } 5195 depthSizeOld[depth] = cMax; 5196 depthSizeOld[0] = vMax; 5197 depthSizeOld[depth-1] = fMax; 5198 depthSizeOld[1] = eMax; 5199 5200 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 5201 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 5202 5203 depthSizeOld[depth] = cEnd - cStart; 5204 depthSizeOld[0] = vEnd - vStart; 5205 depthSizeOld[depth-1] = fEnd - fStart; 5206 depthSizeOld[1] = eEnd - eStart; 5207 5208 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 5209 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 5210 for (n = 0; n < numNeighbors; ++n) { 5211 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 5212 } 5213 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 5214 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 5215 /* Calculate new point SF */ 5216 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 5217 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 5218 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 5219 for (l = 0, m = 0; l < numLeaves; ++l) { 5220 PetscInt p = localPoints[l]; 5221 PetscInt rp = remotePoints[l].index, n; 5222 PetscMPIInt rrank = remotePoints[l].rank; 5223 5224 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 5225 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 5226 switch (refiner) { 5227 case 1: 5228 /* Simplicial 2D */ 5229 if ((p >= vStart) && (p < vEnd)) { 5230 /* Old vertices stay the same */ 5231 localPointsNew[m] = vStartNew + (p - vStart); 5232 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5233 remotePointsNew[m].rank = rrank; 5234 ++m; 5235 } else if ((p >= fStart) && (p < fEnd)) { 5236 /* Old faces add new faces and vertex */ 5237 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5238 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5239 remotePointsNew[m].rank = rrank; 5240 ++m; 5241 for (r = 0; r < 2; ++r, ++m) { 5242 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5243 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5244 remotePointsNew[m].rank = rrank; 5245 } 5246 } else if ((p >= cStart) && (p < cEnd)) { 5247 /* Old cells add new cells and interior faces */ 5248 for (r = 0; r < 4; ++r, ++m) { 5249 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5250 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5251 remotePointsNew[m].rank = rrank; 5252 } 5253 for (r = 0; r < 3; ++r, ++m) { 5254 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5255 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 5256 remotePointsNew[m].rank = rrank; 5257 } 5258 } 5259 break; 5260 case 2: 5261 /* Hex 2D */ 5262 if ((p >= vStart) && (p < vEnd)) { 5263 /* Old vertices stay the same */ 5264 localPointsNew[m] = vStartNew + (p - vStart); 5265 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5266 remotePointsNew[m].rank = rrank; 5267 ++m; 5268 } else if ((p >= fStart) && (p < fEnd)) { 5269 /* Old faces add new faces and vertex */ 5270 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5271 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5272 remotePointsNew[m].rank = rrank; 5273 ++m; 5274 for (r = 0; r < 2; ++r, ++m) { 5275 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5276 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5277 remotePointsNew[m].rank = rrank; 5278 } 5279 } else if ((p >= cStart) && (p < cEnd)) { 5280 /* Old cells add new cells and interior faces */ 5281 for (r = 0; r < 4; ++r, ++m) { 5282 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5283 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5284 remotePointsNew[m].rank = rrank; 5285 } 5286 for (r = 0; r < 4; ++r, ++m) { 5287 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 5288 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 5289 remotePointsNew[m].rank = rrank; 5290 } 5291 } 5292 break; 5293 case 3: 5294 /* Hybrid simplicial 2D */ 5295 if ((p >= vStart) && (p < vEnd)) { 5296 /* Old vertices stay the same */ 5297 localPointsNew[m] = vStartNew + (p - vStart); 5298 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 5299 remotePointsNew[m].rank = rrank; 5300 ++m; 5301 } else if ((p >= fStart) && (p < fMax)) { 5302 /* Old interior faces add new faces and vertex */ 5303 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 5304 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 5305 remotePointsNew[m].rank = rrank; 5306 ++m; 5307 for (r = 0; r < 2; ++r, ++m) { 5308 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 5309 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 5310 remotePointsNew[m].rank = rrank; 5311 } 5312 } else if ((p >= fMax) && (p < fEnd)) { 5313 /* Old hybrid faces stay the same */ 5314 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 5315 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 5316 remotePointsNew[m].rank = rrank; 5317 ++m; 5318 } else if ((p >= cStart) && (p < cMax)) { 5319 /* Old interior cells add new cells and interior faces */ 5320 for (r = 0; r < 4; ++r, ++m) { 5321 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5322 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5323 remotePointsNew[m].rank = rrank; 5324 } 5325 for (r = 0; r < 3; ++r, ++m) { 5326 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 5327 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 5328 remotePointsNew[m].rank = rrank; 5329 } 5330 } else if ((p >= cStart) && (p < cMax)) { 5331 /* Old hybrid cells add new cells and hybrid face */ 5332 for (r = 0; r < 2; ++r, ++m) { 5333 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 5334 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 5335 remotePointsNew[m].rank = rrank; 5336 } 5337 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 5338 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]); 5339 remotePointsNew[m].rank = rrank; 5340 ++m; 5341 } 5342 break; 5343 default: 5344 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5345 } 5346 } 5347 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 5348 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 5349 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 5350 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 5351 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 5352 PetscFunctionReturn(0); 5353 } 5354 5355 #undef __FUNCT__ 5356 #define __FUNCT__ "CellRefinerCreateLabels" 5357 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5358 { 5359 PetscInt numLabels, l; 5360 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 5361 PetscErrorCode ierr; 5362 5363 PetscFunctionBegin; 5364 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5365 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5366 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5367 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5368 5369 cStartNew = 0; 5370 vStartNew = depthSize[2]; 5371 fStartNew = depthSize[2] + depthSize[0]; 5372 5373 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 5374 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5375 switch (refiner) { 5376 case 3: 5377 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5378 cMax = PetscMin(cEnd, cMax); 5379 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5380 fMax = PetscMin(fEnd, fMax); 5381 } 5382 for (l = 0; l < numLabels; ++l) { 5383 DMLabel label, labelNew; 5384 const char *lname; 5385 PetscBool isDepth; 5386 IS valueIS; 5387 const PetscInt *values; 5388 PetscInt numValues, val; 5389 5390 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 5391 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 5392 if (isDepth) continue; 5393 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 5394 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 5395 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 5396 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 5397 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 5398 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 5399 for (val = 0; val < numValues; ++val) { 5400 IS pointIS; 5401 const PetscInt *points; 5402 PetscInt numPoints, n; 5403 5404 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 5405 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 5406 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 5407 for (n = 0; n < numPoints; ++n) { 5408 const PetscInt p = points[n]; 5409 switch (refiner) { 5410 case 1: 5411 /* Simplicial 2D */ 5412 if ((p >= vStart) && (p < vEnd)) { 5413 /* Old vertices stay the same */ 5414 newp = vStartNew + (p - vStart); 5415 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5416 } else if ((p >= fStart) && (p < fEnd)) { 5417 /* Old faces add new faces and vertex */ 5418 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5419 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5420 for (r = 0; r < 2; ++r) { 5421 newp = fStartNew + (p - fStart)*2 + r; 5422 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5423 } 5424 } else if ((p >= cStart) && (p < cEnd)) { 5425 /* Old cells add new cells and interior faces */ 5426 for (r = 0; r < 4; ++r) { 5427 newp = cStartNew + (p - cStart)*4 + r; 5428 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5429 } 5430 for (r = 0; r < 3; ++r) { 5431 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5432 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5433 } 5434 } 5435 break; 5436 case 2: 5437 /* Hex 2D */ 5438 if ((p >= vStart) && (p < vEnd)) { 5439 /* Old vertices stay the same */ 5440 newp = vStartNew + (p - vStart); 5441 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5442 } else if ((p >= fStart) && (p < fEnd)) { 5443 /* Old faces add new faces and vertex */ 5444 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5445 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5446 for (r = 0; r < 2; ++r) { 5447 newp = fStartNew + (p - fStart)*2 + r; 5448 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5449 } 5450 } else if ((p >= cStart) && (p < cEnd)) { 5451 /* Old cells add new cells and interior faces and vertex */ 5452 for (r = 0; r < 4; ++r) { 5453 newp = cStartNew + (p - cStart)*4 + r; 5454 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5455 } 5456 for (r = 0; r < 4; ++r) { 5457 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 5458 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5459 } 5460 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 5461 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5462 } 5463 break; 5464 case 3: 5465 /* Hybrid simplicial 2D */ 5466 if ((p >= vStart) && (p < vEnd)) { 5467 /* Old vertices stay the same */ 5468 newp = vStartNew + (p - vStart); 5469 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5470 } else if ((p >= fStart) && (p < fMax)) { 5471 /* Old interior faces add new faces and vertex */ 5472 newp = vStartNew + (vEnd - vStart) + (p - fStart); 5473 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5474 for (r = 0; r < 2; ++r) { 5475 newp = fStartNew + (p - fStart)*2 + r; 5476 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5477 } 5478 } else if ((p >= fMax) && (p < fEnd)) { 5479 /* Old hybrid faces stay the same */ 5480 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 5481 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5482 } else if ((p >= cStart) && (p < cMax)) { 5483 /* Old interior cells add new cells and interior faces */ 5484 for (r = 0; r < 4; ++r) { 5485 newp = cStartNew + (p - cStart)*4 + r; 5486 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5487 } 5488 for (r = 0; r < 3; ++r) { 5489 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 5490 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5491 } 5492 } else if ((p >= cMax) && (p < cEnd)) { 5493 /* Old hybrid cells add new cells and hybrid face */ 5494 for (r = 0; r < 2; ++r) { 5495 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 5496 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5497 } 5498 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 5499 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 5500 } 5501 break; 5502 default: 5503 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5504 } 5505 } 5506 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 5507 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 5508 } 5509 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 5510 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 5511 if (0) { 5512 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 5513 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 5514 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 5515 } 5516 } 5517 PetscFunctionReturn(0); 5518 } 5519 5520 #undef __FUNCT__ 5521 #define __FUNCT__ "DMPlexRefine_Uniform" 5522 /* This will only work for interpolated meshes */ 5523 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 5524 { 5525 DM rdm; 5526 PetscInt *depthSize; 5527 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 5528 PetscErrorCode ierr; 5529 5530 PetscFunctionBegin; 5531 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 5532 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 5533 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5534 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 5535 /* Calculate number of new points of each depth */ 5536 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5537 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 5538 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 5539 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 5540 /* Step 1: Set chart */ 5541 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 5542 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 5543 /* Step 2: Set cone/support sizes */ 5544 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5545 /* Step 3: Setup refined DM */ 5546 ierr = DMSetUp(rdm);CHKERRQ(ierr); 5547 /* Step 4: Set cones and supports */ 5548 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5549 /* Step 5: Stratify */ 5550 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 5551 /* Step 6: Set coordinates for vertices */ 5552 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5553 /* Step 7: Create pointSF */ 5554 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5555 /* Step 8: Create labels */ 5556 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 5557 ierr = PetscFree(depthSize);CHKERRQ(ierr); 5558 5559 *dmRefined = rdm; 5560 PetscFunctionReturn(0); 5561 } 5562 5563 #undef __FUNCT__ 5564 #define __FUNCT__ "DMPlexSetRefinementUniform" 5565 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 5566 { 5567 DM_Plex *mesh = (DM_Plex*) dm->data; 5568 5569 PetscFunctionBegin; 5570 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5571 mesh->refinementUniform = refinementUniform; 5572 PetscFunctionReturn(0); 5573 } 5574 5575 #undef __FUNCT__ 5576 #define __FUNCT__ "DMPlexGetRefinementUniform" 5577 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 5578 { 5579 DM_Plex *mesh = (DM_Plex*) dm->data; 5580 5581 PetscFunctionBegin; 5582 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5583 PetscValidPointer(refinementUniform, 2); 5584 *refinementUniform = mesh->refinementUniform; 5585 PetscFunctionReturn(0); 5586 } 5587 5588 #undef __FUNCT__ 5589 #define __FUNCT__ "DMPlexSetRefinementLimit" 5590 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 5591 { 5592 DM_Plex *mesh = (DM_Plex*) dm->data; 5593 5594 PetscFunctionBegin; 5595 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5596 mesh->refinementLimit = refinementLimit; 5597 PetscFunctionReturn(0); 5598 } 5599 5600 #undef __FUNCT__ 5601 #define __FUNCT__ "DMPlexGetRefinementLimit" 5602 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 5603 { 5604 DM_Plex *mesh = (DM_Plex*) dm->data; 5605 5606 PetscFunctionBegin; 5607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5608 PetscValidPointer(refinementLimit, 2); 5609 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 5610 *refinementLimit = mesh->refinementLimit; 5611 PetscFunctionReturn(0); 5612 } 5613 5614 #undef __FUNCT__ 5615 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 5616 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 5617 { 5618 PetscInt dim, cStart, coneSize, cMax; 5619 PetscErrorCode ierr; 5620 5621 PetscFunctionBegin; 5622 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5623 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 5624 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 5625 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5626 switch (dim) { 5627 case 2: 5628 switch (coneSize) { 5629 case 3: 5630 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 5631 else *cellRefiner = 1; /* Triangular */ 5632 break; 5633 case 4: 5634 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 5635 else *cellRefiner = 2; /* Quadrilateral */ 5636 break; 5637 default: 5638 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 5639 } 5640 break; 5641 default: 5642 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 5643 } 5644 PetscFunctionReturn(0); 5645 } 5646 5647 #undef __FUNCT__ 5648 #define __FUNCT__ "DMRefine_Plex" 5649 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 5650 { 5651 PetscReal refinementLimit; 5652 PetscInt dim, cStart, cEnd; 5653 char genname[1024], *name = NULL; 5654 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5655 PetscErrorCode ierr; 5656 5657 PetscFunctionBegin; 5658 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 5659 if (isUniform) { 5660 CellRefiner cellRefiner; 5661 5662 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 5663 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 5664 PetscFunctionReturn(0); 5665 } 5666 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 5667 if (refinementLimit == 0.0) PetscFunctionReturn(0); 5668 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5669 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5670 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5671 if (flg) name = genname; 5672 if (name) { 5673 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5674 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5675 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5676 } 5677 switch (dim) { 5678 case 2: 5679 if (!name || isTriangle) { 5680 #if defined(PETSC_HAVE_TRIANGLE) 5681 double *maxVolumes; 5682 PetscInt c; 5683 5684 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 5685 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5686 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5687 #else 5688 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 5689 #endif 5690 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5691 break; 5692 case 3: 5693 if (!name || isCTetgen) { 5694 #if defined(PETSC_HAVE_CTETGEN) 5695 PetscReal *maxVolumes; 5696 PetscInt c; 5697 5698 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 5699 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5700 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5701 #else 5702 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5703 #endif 5704 } else if (isTetgen) { 5705 #if defined(PETSC_HAVE_TETGEN) 5706 double *maxVolumes; 5707 PetscInt c; 5708 5709 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 5710 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 5711 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 5712 #else 5713 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5714 #endif 5715 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5716 break; 5717 default: 5718 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 5719 } 5720 PetscFunctionReturn(0); 5721 } 5722 5723 #undef __FUNCT__ 5724 #define __FUNCT__ "DMPlexGetDepth" 5725 /*@ 5726 DMPlexGetDepth - get the number of strata 5727 5728 Not Collective 5729 5730 Input Parameters: 5731 . dm - The DMPlex object 5732 5733 Output Parameters: 5734 . depth - number of strata 5735 5736 Level: developer 5737 5738 Notes: 5739 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 5740 5741 .keywords: mesh, points 5742 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 5743 @*/ 5744 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5745 { 5746 PetscInt d; 5747 PetscErrorCode ierr; 5748 5749 PetscFunctionBegin; 5750 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5751 PetscValidPointer(depth, 2); 5752 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 5753 *depth = d-1; 5754 PetscFunctionReturn(0); 5755 } 5756 5757 #undef __FUNCT__ 5758 #define __FUNCT__ "DMPlexGetDepthStratum" 5759 /*@ 5760 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 5761 5762 Not Collective 5763 5764 Input Parameters: 5765 + dm - The DMPlex object 5766 - stratumValue - The requested depth 5767 5768 Output Parameters: 5769 + start - The first point at this depth 5770 - end - One beyond the last point at this depth 5771 5772 Level: developer 5773 5774 .keywords: mesh, points 5775 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 5776 @*/ 5777 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 5778 { 5779 DM_Plex *mesh = (DM_Plex*) dm->data; 5780 DMLabel next = mesh->labels; 5781 PetscBool flg = PETSC_FALSE; 5782 PetscInt depth; 5783 PetscErrorCode ierr; 5784 5785 PetscFunctionBegin; 5786 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5787 if (stratumValue < 0) { 5788 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 5789 PetscFunctionReturn(0); 5790 } else { 5791 PetscInt pStart, pEnd; 5792 5793 if (start) *start = 0; 5794 if (end) *end = 0; 5795 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5796 if (pStart == pEnd) PetscFunctionReturn(0); 5797 } 5798 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 5799 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 5800 /* We should have a generic GetLabel() and a Label class */ 5801 while (next) { 5802 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 5803 if (flg) break; 5804 next = next->next; 5805 } 5806 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 5807 depth = stratumValue; 5808 if ((depth < 0) || (depth >= next->numStrata)) { 5809 if (start) *start = 0; 5810 if (end) *end = 0; 5811 } else { 5812 if (start) *start = next->points[next->stratumOffsets[depth]]; 5813 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 5814 } 5815 PetscFunctionReturn(0); 5816 } 5817 5818 #undef __FUNCT__ 5819 #define __FUNCT__ "DMPlexGetHeightStratum" 5820 /*@ 5821 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 5822 5823 Not Collective 5824 5825 Input Parameters: 5826 + dm - The DMPlex object 5827 - stratumValue - The requested height 5828 5829 Output Parameters: 5830 + start - The first point at this height 5831 - end - One beyond the last point at this height 5832 5833 Level: developer 5834 5835 .keywords: mesh, points 5836 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 5837 @*/ 5838 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 5839 { 5840 DM_Plex *mesh = (DM_Plex*) dm->data; 5841 DMLabel next = mesh->labels; 5842 PetscBool flg = PETSC_FALSE; 5843 PetscInt depth; 5844 PetscErrorCode ierr; 5845 5846 PetscFunctionBegin; 5847 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5848 if (stratumValue < 0) { 5849 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 5850 } else { 5851 PetscInt pStart, pEnd; 5852 5853 if (start) *start = 0; 5854 if (end) *end = 0; 5855 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5856 if (pStart == pEnd) PetscFunctionReturn(0); 5857 } 5858 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 5859 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 5860 /* We should have a generic GetLabel() and a Label class */ 5861 while (next) { 5862 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 5863 if (flg) break; 5864 next = next->next; 5865 } 5866 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 5867 depth = next->stratumValues[next->numStrata-1] - stratumValue; 5868 if ((depth < 0) || (depth >= next->numStrata)) { 5869 if (start) *start = 0; 5870 if (end) *end = 0; 5871 } else { 5872 if (start) *start = next->points[next->stratumOffsets[depth]]; 5873 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 5874 } 5875 PetscFunctionReturn(0); 5876 } 5877 5878 #undef __FUNCT__ 5879 #define __FUNCT__ "DMPlexCreateSectionInitial" 5880 /* Set the number of dof on each point and separate by fields */ 5881 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 5882 { 5883 PetscInt *numDofTot; 5884 PetscInt pStart = 0, pEnd = 0; 5885 PetscInt p, d, f; 5886 PetscErrorCode ierr; 5887 5888 PetscFunctionBegin; 5889 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 5890 for (d = 0; d <= dim; ++d) { 5891 numDofTot[d] = 0; 5892 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 5893 } 5894 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 5895 if (numFields > 0) { 5896 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 5897 if (numComp) { 5898 for (f = 0; f < numFields; ++f) { 5899 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 5900 } 5901 } 5902 } 5903 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5904 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 5905 for (d = 0; d <= dim; ++d) { 5906 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 5907 for (p = pStart; p < pEnd; ++p) { 5908 for (f = 0; f < numFields; ++f) { 5909 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 5910 } 5911 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 5912 } 5913 } 5914 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 5915 PetscFunctionReturn(0); 5916 } 5917 5918 #undef __FUNCT__ 5919 #define __FUNCT__ "DMPlexCreateSectionBCDof" 5920 /* Set the number of dof on each point and separate by fields 5921 If constDof is PETSC_DETERMINE, constrain every dof on the point 5922 */ 5923 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 5924 { 5925 PetscInt numFields; 5926 PetscInt bc; 5927 PetscErrorCode ierr; 5928 5929 PetscFunctionBegin; 5930 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5931 for (bc = 0; bc < numBC; ++bc) { 5932 PetscInt field = 0; 5933 const PetscInt *idx; 5934 PetscInt n, i; 5935 5936 if (numFields) field = bcField[bc]; 5937 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 5938 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 5939 for (i = 0; i < n; ++i) { 5940 const PetscInt p = idx[i]; 5941 PetscInt numConst = constDof; 5942 5943 /* Constrain every dof on the point */ 5944 if (numConst < 0) { 5945 if (numFields) { 5946 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 5947 } else { 5948 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 5949 } 5950 } 5951 if (numFields) { 5952 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 5953 } 5954 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 5955 } 5956 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 5957 } 5958 PetscFunctionReturn(0); 5959 } 5960 5961 #undef __FUNCT__ 5962 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 5963 /* Set the constrained indices on each point and separate by fields */ 5964 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 5965 { 5966 PetscInt *maxConstraints; 5967 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 5968 PetscErrorCode ierr; 5969 5970 PetscFunctionBegin; 5971 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5972 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5973 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 5974 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 5975 for (p = pStart; p < pEnd; ++p) { 5976 PetscInt cdof; 5977 5978 if (numFields) { 5979 for (f = 0; f < numFields; ++f) { 5980 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 5981 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 5982 } 5983 } else { 5984 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 5985 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 5986 } 5987 } 5988 for (f = 0; f < numFields; ++f) { 5989 maxConstraints[numFields] += maxConstraints[f]; 5990 } 5991 if (maxConstraints[numFields]) { 5992 PetscInt *indices; 5993 5994 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 5995 for (p = pStart; p < pEnd; ++p) { 5996 PetscInt cdof, d; 5997 5998 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 5999 if (cdof) { 6000 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 6001 if (numFields) { 6002 PetscInt numConst = 0, foff = 0; 6003 6004 for (f = 0; f < numFields; ++f) { 6005 PetscInt cfdof, fdof; 6006 6007 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 6008 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 6009 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 6010 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 6011 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 6012 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 6013 numConst += cfdof; 6014 foff += fdof; 6015 } 6016 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 6017 } else { 6018 for (d = 0; d < cdof; ++d) indices[d] = d; 6019 } 6020 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 6021 } 6022 } 6023 ierr = PetscFree(indices);CHKERRQ(ierr); 6024 } 6025 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 6026 PetscFunctionReturn(0); 6027 } 6028 6029 #undef __FUNCT__ 6030 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 6031 /* Set the constrained field indices on each point */ 6032 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 6033 { 6034 const PetscInt *points, *indices; 6035 PetscInt numFields, maxDof, numPoints, p, numConstraints; 6036 PetscErrorCode ierr; 6037 6038 PetscFunctionBegin; 6039 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6040 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 6041 6042 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 6043 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 6044 if (!constraintIndices) { 6045 PetscInt *idx, i; 6046 6047 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6048 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 6049 for (i = 0; i < maxDof; ++i) idx[i] = i; 6050 for (p = 0; p < numPoints; ++p) { 6051 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 6052 } 6053 ierr = PetscFree(idx);CHKERRQ(ierr); 6054 } else { 6055 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 6056 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 6057 for (p = 0; p < numPoints; ++p) { 6058 PetscInt fcdof; 6059 6060 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 6061 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); 6062 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 6063 } 6064 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 6065 } 6066 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 6067 PetscFunctionReturn(0); 6068 } 6069 6070 #undef __FUNCT__ 6071 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 6072 /* Set the constrained indices on each point and separate by fields */ 6073 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 6074 { 6075 PetscInt *indices; 6076 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 6077 PetscErrorCode ierr; 6078 6079 PetscFunctionBegin; 6080 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6081 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 6082 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6083 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 6084 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6085 for (p = pStart; p < pEnd; ++p) { 6086 PetscInt cdof, d; 6087 6088 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6089 if (cdof) { 6090 PetscInt numConst = 0, foff = 0; 6091 6092 for (f = 0; f < numFields; ++f) { 6093 const PetscInt *fcind; 6094 PetscInt fdof, fcdof; 6095 6096 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 6097 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 6098 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 6099 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 6100 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 6101 foff += fdof; 6102 numConst += fcdof; 6103 } 6104 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 6105 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 6106 } 6107 } 6108 ierr = PetscFree(indices);CHKERRQ(ierr); 6109 PetscFunctionReturn(0); 6110 } 6111 6112 #undef __FUNCT__ 6113 #define __FUNCT__ "DMPlexCreateSection" 6114 /*@C 6115 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 6116 6117 Not Collective 6118 6119 Input Parameters: 6120 + dm - The DMPlex object 6121 . dim - The spatial dimension of the problem 6122 . numFields - The number of fields in the problem 6123 . numComp - An array of size numFields that holds the number of components for each field 6124 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 6125 . numBC - The number of boundary conditions 6126 . bcField - An array of size numBC giving the field number for each boundry condition 6127 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 6128 6129 Output Parameter: 6130 . section - The PetscSection object 6131 6132 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 6133 nubmer of dof for field 0 on each edge. 6134 6135 Level: developer 6136 6137 Fortran Notes: 6138 A Fortran 90 version is available as DMPlexCreateSectionF90() 6139 6140 .keywords: mesh, elements 6141 .seealso: DMPlexCreate(), PetscSectionCreate() 6142 @*/ 6143 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 6144 { 6145 PetscErrorCode ierr; 6146 6147 PetscFunctionBegin; 6148 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 6149 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 6150 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 6151 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 6152 { 6153 PetscBool view = PETSC_FALSE; 6154 6155 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 6156 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 6157 } 6158 PetscFunctionReturn(0); 6159 } 6160 6161 #undef __FUNCT__ 6162 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 6163 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 6164 { 6165 PetscSection section; 6166 PetscErrorCode ierr; 6167 6168 PetscFunctionBegin; 6169 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 6170 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6171 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 6172 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6173 PetscFunctionReturn(0); 6174 } 6175 6176 #undef __FUNCT__ 6177 #define __FUNCT__ "DMPlexGetCoordinateSection" 6178 /*@ 6179 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6180 6181 Not Collective 6182 6183 Input Parameter: 6184 . dm - The DMPlex object 6185 6186 Output Parameter: 6187 . section - The PetscSection object 6188 6189 Level: intermediate 6190 6191 .keywords: mesh, coordinates 6192 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6193 @*/ 6194 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 6195 { 6196 DM cdm; 6197 PetscErrorCode ierr; 6198 6199 PetscFunctionBegin; 6200 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6201 PetscValidPointer(section, 2); 6202 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6203 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 6204 PetscFunctionReturn(0); 6205 } 6206 6207 #undef __FUNCT__ 6208 #define __FUNCT__ "DMPlexSetCoordinateSection" 6209 /*@ 6210 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 6211 6212 Not Collective 6213 6214 Input Parameters: 6215 + dm - The DMPlex object 6216 - section - The PetscSection object 6217 6218 Level: intermediate 6219 6220 .keywords: mesh, coordinates 6221 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 6222 @*/ 6223 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 6224 { 6225 DM cdm; 6226 PetscErrorCode ierr; 6227 6228 PetscFunctionBegin; 6229 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6230 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 6231 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6232 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 6233 PetscFunctionReturn(0); 6234 } 6235 6236 #undef __FUNCT__ 6237 #define __FUNCT__ "DMPlexGetConeSection" 6238 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 6239 { 6240 DM_Plex *mesh = (DM_Plex*) dm->data; 6241 6242 PetscFunctionBegin; 6243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6244 if (section) *section = mesh->coneSection; 6245 PetscFunctionReturn(0); 6246 } 6247 6248 #undef __FUNCT__ 6249 #define __FUNCT__ "DMPlexGetCones" 6250 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 6251 { 6252 DM_Plex *mesh = (DM_Plex*) dm->data; 6253 6254 PetscFunctionBegin; 6255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6256 if (cones) *cones = mesh->cones; 6257 PetscFunctionReturn(0); 6258 } 6259 6260 #undef __FUNCT__ 6261 #define __FUNCT__ "DMPlexGetConeOrientations" 6262 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 6263 { 6264 DM_Plex *mesh = (DM_Plex*) dm->data; 6265 6266 PetscFunctionBegin; 6267 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6268 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 6269 PetscFunctionReturn(0); 6270 } 6271 6272 /******************************** FEM Support **********************************/ 6273 6274 #undef __FUNCT__ 6275 #define __FUNCT__ "DMPlexVecGetClosure" 6276 /*@C 6277 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6278 6279 Not collective 6280 6281 Input Parameters: 6282 + dm - The DM 6283 . section - The section describing the layout in v, or NULL to use the default section 6284 . v - The local vector 6285 - point - The sieve point in the DM 6286 6287 Output Parameters: 6288 + csize - The number of values in the closure, or NULL 6289 - values - The array of values, which is a borrowed array and should not be freed 6290 6291 Fortran Notes: 6292 Since it returns an array, this routine is only available in Fortran 90, and you must 6293 include petsc.h90 in your code. 6294 6295 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6296 6297 Level: intermediate 6298 6299 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6300 @*/ 6301 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6302 { 6303 PetscScalar *array, *vArray; 6304 PetscInt *points = NULL; 6305 PetscInt offsets[32]; 6306 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 6307 PetscErrorCode ierr; 6308 6309 PetscFunctionBegin; 6310 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6311 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6312 if (!section) { 6313 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6314 } 6315 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6316 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6317 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6318 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6319 /* Compress out points not in the section */ 6320 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6321 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6322 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6323 points[q*2] = points[p]; 6324 points[q*2+1] = points[p+1]; 6325 ++q; 6326 } 6327 } 6328 numPoints = q; 6329 for (p = 0, size = 0; p < numPoints*2; p += 2) { 6330 PetscInt dof, fdof; 6331 6332 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6333 for (f = 0; f < numFields; ++f) { 6334 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6335 offsets[f+1] += fdof; 6336 } 6337 size += dof; 6338 } 6339 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6340 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 6341 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 6342 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 6343 for (p = 0; p < numPoints*2; p += 2) { 6344 PetscInt o = points[p+1]; 6345 PetscInt dof, off, d; 6346 PetscScalar *varr; 6347 6348 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6349 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 6350 varr = &vArray[off]; 6351 if (numFields) { 6352 PetscInt fdof, foff, fcomp, f, c; 6353 6354 for (f = 0, foff = 0; f < numFields; ++f) { 6355 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6356 if (o >= 0) { 6357 for (d = 0; d < fdof; ++d, ++offsets[f]) { 6358 array[offsets[f]] = varr[foff+d]; 6359 } 6360 } else { 6361 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6362 for (d = fdof/fcomp-1; d >= 0; --d) { 6363 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 6364 array[offsets[f]] = varr[foff+d*fcomp+c]; 6365 } 6366 } 6367 } 6368 foff += fdof; 6369 } 6370 } else { 6371 if (o >= 0) { 6372 for (d = 0; d < dof; ++d, ++offsets[0]) { 6373 array[offsets[0]] = varr[d]; 6374 } 6375 } else { 6376 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 6377 array[offsets[0]] = varr[d]; 6378 } 6379 } 6380 } 6381 } 6382 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6383 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 6384 if (csize) *csize = size; 6385 *values = array; 6386 PetscFunctionReturn(0); 6387 } 6388 6389 #undef __FUNCT__ 6390 #define __FUNCT__ "DMPlexVecRestoreClosure" 6391 /*@C 6392 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6393 6394 Not collective 6395 6396 Input Parameters: 6397 + dm - The DM 6398 . section - The section describing the layout in v, or NULL to use the default section 6399 . v - The local vector 6400 . point - The sieve point in the DM 6401 . csize - The number of values in the closure, or NULL 6402 - values - The array of values, which is a borrowed array and should not be freed 6403 6404 Fortran Notes: 6405 Since it returns an array, this routine is only available in Fortran 90, and you must 6406 include petsc.h90 in your code. 6407 6408 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6409 6410 Level: intermediate 6411 6412 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6413 @*/ 6414 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6415 { 6416 PetscInt size = 0; 6417 PetscErrorCode ierr; 6418 6419 PetscFunctionBegin; 6420 /* Should work without recalculating size */ 6421 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 6422 PetscFunctionReturn(0); 6423 } 6424 6425 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 6426 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 6427 6428 #undef __FUNCT__ 6429 #define __FUNCT__ "updatePoint_private" 6430 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6431 { 6432 PetscInt cdof; /* The number of constraints on this point */ 6433 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6434 PetscScalar *a; 6435 PetscInt off, cind = 0, k; 6436 PetscErrorCode ierr; 6437 6438 PetscFunctionBegin; 6439 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6440 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6441 a = &array[off]; 6442 if (!cdof || setBC) { 6443 if (orientation >= 0) { 6444 for (k = 0; k < dof; ++k) { 6445 fuse(&a[k], values[k]); 6446 } 6447 } else { 6448 for (k = 0; k < dof; ++k) { 6449 fuse(&a[k], values[dof-k-1]); 6450 } 6451 } 6452 } else { 6453 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6454 if (orientation >= 0) { 6455 for (k = 0; k < dof; ++k) { 6456 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6457 fuse(&a[k], values[k]); 6458 } 6459 } else { 6460 for (k = 0; k < dof; ++k) { 6461 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6462 fuse(&a[k], values[dof-k-1]); 6463 } 6464 } 6465 } 6466 PetscFunctionReturn(0); 6467 } 6468 6469 #undef __FUNCT__ 6470 #define __FUNCT__ "updatePointFields_private" 6471 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 6472 { 6473 PetscScalar *a; 6474 PetscInt numFields, off, foff, f; 6475 PetscErrorCode ierr; 6476 6477 PetscFunctionBegin; 6478 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6479 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6480 a = &array[off]; 6481 for (f = 0, foff = 0; f < numFields; ++f) { 6482 PetscInt fdof, fcomp, fcdof; 6483 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6484 PetscInt cind = 0, k, c; 6485 6486 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6487 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6488 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6489 if (!fcdof || setBC) { 6490 if (orientation >= 0) { 6491 for (k = 0; k < fdof; ++k) { 6492 fuse(&a[foff+k], values[foffs[f]+k]); 6493 } 6494 } else { 6495 for (k = fdof/fcomp-1; k >= 0; --k) { 6496 for (c = 0; c < fcomp; ++c) { 6497 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6498 } 6499 } 6500 } 6501 } else { 6502 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6503 if (orientation >= 0) { 6504 for (k = 0; k < fdof; ++k) { 6505 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 6506 fuse(&a[foff+k], values[foffs[f]+k]); 6507 } 6508 } else { 6509 for (k = fdof/fcomp-1; k >= 0; --k) { 6510 for (c = 0; c < fcomp; ++c) { 6511 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 6512 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 6513 } 6514 } 6515 } 6516 } 6517 foff += fdof; 6518 foffs[f] += fdof; 6519 } 6520 PetscFunctionReturn(0); 6521 } 6522 6523 #undef __FUNCT__ 6524 #define __FUNCT__ "DMPlexVecSetClosure" 6525 /*@C 6526 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6527 6528 Not collective 6529 6530 Input Parameters: 6531 + dm - The DM 6532 . section - The section describing the layout in v, or NULL to use the default sectionw 6533 . v - The local vector 6534 . point - The sieve point in the DM 6535 . values - The array of values, which is a borrowed array and should not be freed 6536 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6537 6538 Fortran Notes: 6539 Since it returns an array, this routine is only available in Fortran 90, and you must 6540 include petsc.h90 in your code. 6541 6542 Level: intermediate 6543 6544 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6545 @*/ 6546 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6547 { 6548 PetscScalar *array; 6549 PetscInt *points = NULL; 6550 PetscInt offsets[32]; 6551 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 6552 PetscErrorCode ierr; 6553 6554 PetscFunctionBegin; 6555 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6556 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6557 if (!section) { 6558 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6559 } 6560 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6561 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6562 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6563 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6564 /* Compress out points not in the section */ 6565 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6566 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6567 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6568 points[q*2] = points[p]; 6569 points[q*2+1] = points[p+1]; 6570 ++q; 6571 } 6572 } 6573 numPoints = q; 6574 for (p = 0; p < numPoints*2; p += 2) { 6575 PetscInt fdof; 6576 6577 for (f = 0; f < numFields; ++f) { 6578 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6579 offsets[f+1] += fdof; 6580 } 6581 } 6582 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6583 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6584 if (numFields) { 6585 switch (mode) { 6586 case INSERT_VALUES: 6587 for (p = 0; p < numPoints*2; p += 2) { 6588 PetscInt o = points[p+1]; 6589 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 6590 } break; 6591 case INSERT_ALL_VALUES: 6592 for (p = 0; p < numPoints*2; p += 2) { 6593 PetscInt o = points[p+1]; 6594 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 6595 } break; 6596 case ADD_VALUES: 6597 for (p = 0; p < numPoints*2; p += 2) { 6598 PetscInt o = points[p+1]; 6599 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 6600 } break; 6601 case ADD_ALL_VALUES: 6602 for (p = 0; p < numPoints*2; p += 2) { 6603 PetscInt o = points[p+1]; 6604 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 6605 } break; 6606 default: 6607 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 6608 } 6609 } else { 6610 switch (mode) { 6611 case INSERT_VALUES: 6612 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6613 PetscInt o = points[p+1]; 6614 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6615 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 6616 } break; 6617 case INSERT_ALL_VALUES: 6618 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6619 PetscInt o = points[p+1]; 6620 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6621 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 6622 } break; 6623 case ADD_VALUES: 6624 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6625 PetscInt o = points[p+1]; 6626 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6627 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 6628 } break; 6629 case ADD_ALL_VALUES: 6630 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 6631 PetscInt o = points[p+1]; 6632 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6633 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 6634 } break; 6635 default: 6636 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 6637 } 6638 } 6639 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6640 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6641 PetscFunctionReturn(0); 6642 } 6643 6644 #undef __FUNCT__ 6645 #define __FUNCT__ "DMPlexPrintMatSetValues" 6646 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], const PetscScalar values[]) 6647 { 6648 PetscMPIInt rank; 6649 PetscInt i, j; 6650 PetscErrorCode ierr; 6651 6652 PetscFunctionBegin; 6653 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 6654 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 6655 for (i = 0; i < numIndices; i++) { 6656 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 6657 } 6658 for (i = 0; i < numIndices; i++) { 6659 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 6660 for (j = 0; j < numIndices; j++) { 6661 #if defined(PETSC_USE_COMPLEX) 6662 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 6663 #else 6664 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 6665 #endif 6666 } 6667 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6668 } 6669 PetscFunctionReturn(0); 6670 } 6671 6672 #undef __FUNCT__ 6673 #define __FUNCT__ "indicesPoint_private" 6674 /* . off - The global offset of this point */ 6675 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 6676 { 6677 PetscInt dof; /* The number of unknowns on this point */ 6678 PetscInt cdof; /* The number of constraints on this point */ 6679 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6680 PetscInt cind = 0, k; 6681 PetscErrorCode ierr; 6682 6683 PetscFunctionBegin; 6684 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6685 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6686 if (!cdof || setBC) { 6687 if (orientation >= 0) { 6688 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 6689 } else { 6690 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 6691 } 6692 } else { 6693 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6694 if (orientation >= 0) { 6695 for (k = 0; k < dof; ++k) { 6696 if ((cind < cdof) && (k == cdofs[cind])) { 6697 /* Insert check for returning constrained indices */ 6698 indices[*loff+k] = -(off+k+1); 6699 ++cind; 6700 } else { 6701 indices[*loff+k] = off+k-cind; 6702 } 6703 } 6704 } else { 6705 for (k = 0; k < dof; ++k) { 6706 if ((cind < cdof) && (k == cdofs[cind])) { 6707 /* Insert check for returning constrained indices */ 6708 indices[*loff+dof-k-1] = -(off+k+1); 6709 ++cind; 6710 } else { 6711 indices[*loff+dof-k-1] = off+k-cind; 6712 } 6713 } 6714 } 6715 } 6716 *loff += dof; 6717 PetscFunctionReturn(0); 6718 } 6719 6720 #undef __FUNCT__ 6721 #define __FUNCT__ "indicesPointFields_private" 6722 /* . off - The global offset of this point */ 6723 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 6724 { 6725 PetscInt numFields, foff, f; 6726 PetscErrorCode ierr; 6727 6728 PetscFunctionBegin; 6729 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6730 for (f = 0, foff = 0; f < numFields; ++f) { 6731 PetscInt fdof, fcomp, cfdof; 6732 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6733 PetscInt cind = 0, k, c; 6734 6735 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 6736 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6737 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6738 if (!cfdof || setBC) { 6739 if (orientation >= 0) { 6740 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 6741 } else { 6742 for (k = fdof/fcomp-1; k >= 0; --k) { 6743 for (c = 0; c < fcomp; ++c) { 6744 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 6745 } 6746 } 6747 } 6748 } else { 6749 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6750 if (orientation >= 0) { 6751 for (k = 0; k < fdof; ++k) { 6752 if ((cind < cfdof) && (k == fcdofs[cind])) { 6753 indices[foffs[f]+k] = -(off+foff+k+1); 6754 ++cind; 6755 } else { 6756 indices[foffs[f]+k] = off+foff+k-cind; 6757 } 6758 } 6759 } else { 6760 for (k = fdof/fcomp-1; k >= 0; --k) { 6761 for (c = 0; c < fcomp; ++c) { 6762 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 6763 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 6764 ++cind; 6765 } else { 6766 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 6767 } 6768 } 6769 } 6770 } 6771 } 6772 foff += fdof - cfdof; 6773 foffs[f] += fdof; 6774 } 6775 PetscFunctionReturn(0); 6776 } 6777 6778 #undef __FUNCT__ 6779 #define __FUNCT__ "DMPlexMatSetClosure" 6780 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6781 { 6782 DM_Plex *mesh = (DM_Plex*) dm->data; 6783 PetscInt *points = NULL; 6784 PetscInt *indices; 6785 PetscInt offsets[32]; 6786 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 6787 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 6788 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 6789 PetscErrorCode ierr; 6790 6791 PetscFunctionBegin; 6792 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6793 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 6794 if (useDefault) { 6795 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 6796 } 6797 if (useGlobalDefault) { 6798 if (useDefault) { 6799 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 6800 } else { 6801 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6802 } 6803 } 6804 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6805 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6806 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6807 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6808 /* Compress out points not in the section */ 6809 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6810 for (p = 0, q = 0; p < numPoints*2; p += 2) { 6811 if ((points[p] >= pStart) && (points[p] < pEnd)) { 6812 points[q*2] = points[p]; 6813 points[q*2+1] = points[p+1]; 6814 ++q; 6815 } 6816 } 6817 numPoints = q; 6818 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 6819 PetscInt fdof; 6820 6821 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6822 for (f = 0; f < numFields; ++f) { 6823 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6824 offsets[f+1] += fdof; 6825 } 6826 numIndices += dof; 6827 } 6828 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6829 6830 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 6831 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 6832 if (numFields) { 6833 for (p = 0; p < numPoints*2; p += 2) { 6834 PetscInt o = points[p+1]; 6835 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 6836 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 6837 } 6838 } else { 6839 for (p = 0, off = 0; p < numPoints*2; p += 2) { 6840 PetscInt o = points[p+1]; 6841 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 6842 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 6843 } 6844 } 6845 if (useGlobalDefault && !useDefault) { 6846 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 6847 } 6848 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 6849 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 6850 if (ierr) { 6851 PetscMPIInt rank; 6852 PetscErrorCode ierr2; 6853 6854 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 6855 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 6856 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 6857 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 6858 CHKERRQ(ierr); 6859 } 6860 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 6861 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 6862 PetscFunctionReturn(0); 6863 } 6864 6865 #undef __FUNCT__ 6866 #define __FUNCT__ "DMPlexGetHybridBounds" 6867 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 6868 { 6869 DM_Plex *mesh = (DM_Plex*) dm->data; 6870 PetscInt dim; 6871 PetscErrorCode ierr; 6872 6873 PetscFunctionBegin; 6874 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6875 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6876 if (cMax) *cMax = mesh->hybridPointMax[dim]; 6877 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 6878 if (eMax) *eMax = mesh->hybridPointMax[1]; 6879 if (vMax) *vMax = mesh->hybridPointMax[0]; 6880 PetscFunctionReturn(0); 6881 } 6882 6883 #undef __FUNCT__ 6884 #define __FUNCT__ "DMPlexSetHybridBounds" 6885 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 6886 { 6887 DM_Plex *mesh = (DM_Plex*) dm->data; 6888 PetscInt dim; 6889 PetscErrorCode ierr; 6890 6891 PetscFunctionBegin; 6892 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6893 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6894 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 6895 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 6896 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 6897 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 6898 PetscFunctionReturn(0); 6899 } 6900 6901 #undef __FUNCT__ 6902 #define __FUNCT__ "DMPlexGetVTKCellHeight" 6903 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 6904 { 6905 DM_Plex *mesh = (DM_Plex*) dm->data; 6906 6907 PetscFunctionBegin; 6908 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6909 PetscValidPointer(cellHeight, 2); 6910 *cellHeight = mesh->vtkCellHeight; 6911 PetscFunctionReturn(0); 6912 } 6913 6914 #undef __FUNCT__ 6915 #define __FUNCT__ "DMPlexSetVTKCellHeight" 6916 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 6917 { 6918 DM_Plex *mesh = (DM_Plex*) dm->data; 6919 6920 PetscFunctionBegin; 6921 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6922 mesh->vtkCellHeight = cellHeight; 6923 PetscFunctionReturn(0); 6924 } 6925 6926 #undef __FUNCT__ 6927 #define __FUNCT__ "DMPlexCreateNumbering_Private" 6928 /* We can easily have a form that takes an IS instead */ 6929 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 6930 { 6931 PetscSection section, globalSection; 6932 PetscInt *numbers, p; 6933 PetscErrorCode ierr; 6934 6935 PetscFunctionBegin; 6936 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6937 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 6938 for (p = pStart; p < pEnd; ++p) { 6939 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 6940 } 6941 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 6942 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6943 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 6944 for (p = pStart; p < pEnd; ++p) { 6945 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 6946 } 6947 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 6948 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6949 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 6950 PetscFunctionReturn(0); 6951 } 6952 6953 #undef __FUNCT__ 6954 #define __FUNCT__ "DMPlexGetCellNumbering" 6955 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 6956 { 6957 DM_Plex *mesh = (DM_Plex*) dm->data; 6958 PetscInt cellHeight, cStart, cEnd, cMax; 6959 PetscErrorCode ierr; 6960 6961 PetscFunctionBegin; 6962 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6963 if (!mesh->globalCellNumbers) { 6964 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 6965 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6966 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6967 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 6968 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 6969 } 6970 *globalCellNumbers = mesh->globalCellNumbers; 6971 PetscFunctionReturn(0); 6972 } 6973 6974 #undef __FUNCT__ 6975 #define __FUNCT__ "DMPlexGetVertexNumbering" 6976 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 6977 { 6978 DM_Plex *mesh = (DM_Plex*) dm->data; 6979 PetscInt vStart, vEnd, vMax; 6980 PetscErrorCode ierr; 6981 6982 PetscFunctionBegin; 6983 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6984 if (!mesh->globalVertexNumbers) { 6985 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6986 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 6987 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 6988 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 6989 } 6990 *globalVertexNumbers = mesh->globalVertexNumbers; 6991 PetscFunctionReturn(0); 6992 } 6993 6994 6995 #undef __FUNCT__ 6996 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 6997 /*@C 6998 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 6999 the local section and an SF describing the section point overlap. 7000 7001 Input Parameters: 7002 + s - The PetscSection for the local field layout 7003 . sf - The SF describing parallel layout of the section points 7004 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 7005 . label - The label specifying the points 7006 - labelValue - The label stratum specifying the points 7007 7008 Output Parameter: 7009 . gsection - The PetscSection for the global field layout 7010 7011 Note: This gives negative sizes and offsets to points not owned by this process 7012 7013 Level: developer 7014 7015 .seealso: PetscSectionCreate() 7016 @*/ 7017 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 7018 { 7019 PetscInt *neg; 7020 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 7021 PetscErrorCode ierr; 7022 7023 PetscFunctionBegin; 7024 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 7025 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 7026 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 7027 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 7028 /* Mark ghost points with negative dof */ 7029 for (p = pStart; p < pEnd; ++p) { 7030 PetscInt value; 7031 7032 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 7033 if (value != labelValue) continue; 7034 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 7035 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 7036 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 7037 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 7038 neg[p-pStart] = -(dof+1); 7039 } 7040 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 7041 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 7042 if (nroots >= 0) { 7043 if (nroots > pEnd - pStart) { 7044 PetscInt *tmpDof; 7045 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 7046 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 7047 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 7048 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 7049 for (p = pStart; p < pEnd; ++p) { 7050 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 7051 } 7052 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 7053 } else { 7054 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 7055 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 7056 } 7057 } 7058 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 7059 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7060 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 7061 7062 (*gsection)->atlasOff[p] = off; 7063 7064 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 7065 } 7066 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 7067 globalOff -= off; 7068 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 7069 (*gsection)->atlasOff[p] += globalOff; 7070 7071 neg[p] = -((*gsection)->atlasOff[p]+1); 7072 } 7073 /* Put in negative offsets for ghost points */ 7074 if (nroots >= 0) { 7075 if (nroots > pEnd - pStart) { 7076 PetscInt *tmpOff; 7077 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 7078 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 7079 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 7080 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 7081 for (p = pStart; p < pEnd; ++p) { 7082 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 7083 } 7084 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 7085 } else { 7086 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 7087 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 7088 } 7089 } 7090 ierr = PetscFree(neg);CHKERRQ(ierr); 7091 PetscFunctionReturn(0); 7092 } 7093