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