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