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