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