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