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