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