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