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