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