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