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