1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/isimpl.h> 4 #include <petscsf.h> 5 #include <petscviewerhdf5.h> 6 7 /* Logging support */ 8 PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Stratify, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM; 9 10 PETSC_EXTERN PetscErrorCode VecView_Seq(Vec, PetscViewer); 11 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 12 PETSC_EXTERN PetscErrorCode VecLoad_Default(Vec, PetscViewer); 13 14 #undef __FUNCT__ 15 #define __FUNCT__ "VecView_Plex_Local" 16 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 17 { 18 DM dm; 19 PetscBool isvtk, ishdf5, isseq; 20 PetscErrorCode ierr; 21 22 PetscFunctionBegin; 23 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 24 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 25 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 26 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 27 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 28 if (isvtk || ishdf5) {ierr = DMPlexInsertBoundaryValues(dm, v);CHKERRQ(ierr);} 29 if (isvtk) { 30 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 31 PetscSection section; 32 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 33 34 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 35 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 36 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 37 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 38 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 39 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 40 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 41 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 42 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 43 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 44 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 45 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 46 } else if (cdof && vdof) { 47 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 48 } else if (cdof) { 49 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 50 * vector or just happens to have the same number of dofs as the dimension. */ 51 if (cdof == dim) { 52 ft = PETSC_VTK_CELL_VECTOR_FIELD; 53 } else { 54 ft = PETSC_VTK_CELL_FIELD; 55 } 56 } else if (vdof) { 57 if (vdof == dim) { 58 ft = PETSC_VTK_POINT_VECTOR_FIELD; 59 } else { 60 ft = PETSC_VTK_POINT_FIELD; 61 } 62 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 63 64 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 65 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 66 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 67 } else if (ishdf5) { 68 DM dmBC; 69 Vec gv; 70 const char *name; 71 72 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 73 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 74 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 75 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 76 ierr = DMLocalToGlobalBegin(dmBC, v, INSERT_VALUES, gv);CHKERRQ(ierr); 77 ierr = DMLocalToGlobalEnd(dmBC, v, INSERT_VALUES, gv);CHKERRQ(ierr); 78 ierr = PetscObjectTypeCompare((PetscObject) gv, VECSEQ, &isseq);CHKERRQ(ierr); 79 if (isseq) {ierr = VecView_Seq(gv, viewer);CHKERRQ(ierr);} 80 else {ierr = VecView_MPI(gv, viewer);CHKERRQ(ierr);} 81 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 82 } else { 83 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 84 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 85 } 86 PetscFunctionReturn(0); 87 } 88 89 #undef __FUNCT__ 90 #define __FUNCT__ "VecView_Plex" 91 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 92 { 93 DM dm; 94 PetscBool isvtk, ishdf5, isseq; 95 PetscErrorCode ierr; 96 97 PetscFunctionBegin; 98 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 99 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 100 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 101 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 102 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 103 if (isvtk || ishdf5) { 104 Vec locv; 105 const char *name; 106 107 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 108 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 109 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 110 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 111 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 112 if (ishdf5) { 113 ierr = PetscViewerHDF5PushGroup(viewer, "/fields");CHKERRQ(ierr); 114 /* TODO ierr = PetscViewerHDF5SetTimestep(viewer, istep);CHKERRQ(ierr); */ 115 } 116 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 117 if (ishdf5) {ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr);} 118 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 119 } else { 120 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 121 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 122 } 123 PetscFunctionReturn(0); 124 } 125 126 #undef __FUNCT__ 127 #define __FUNCT__ "VecLoad_Plex_Local" 128 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 129 { 130 DM dm; 131 PetscBool ishdf5; 132 PetscErrorCode ierr; 133 134 PetscFunctionBegin; 135 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 136 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 137 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 138 if (ishdf5) { 139 DM dmBC; 140 Vec gv; 141 const char *name; 142 143 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 144 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 145 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 146 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 147 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 148 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 149 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 150 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 151 } else { 152 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 153 } 154 PetscFunctionReturn(0); 155 } 156 157 #undef __FUNCT__ 158 #define __FUNCT__ "VecLoad_Plex" 159 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 160 { 161 DM dm; 162 PetscBool ishdf5; 163 PetscErrorCode ierr; 164 165 PetscFunctionBegin; 166 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 167 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 168 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 169 if (ishdf5) { 170 Vec locv; 171 const char *name; 172 173 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 174 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 175 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 176 if (ishdf5) { 177 ierr = PetscViewerHDF5PushGroup(viewer, "/fields");CHKERRQ(ierr); 178 /* TODO ierr = PetscViewerHDF5SetTimestep(viewer, istep);CHKERRQ(ierr); */ 179 } 180 ierr = VecLoad_Plex_Local(locv, viewer);CHKERRQ(ierr); 181 if (ishdf5) {ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr);} 182 ierr = DMLocalToGlobalBegin(dm, locv, INSERT_VALUES, v);CHKERRQ(ierr); 183 ierr = DMLocalToGlobalEnd(dm, locv, INSERT_VALUES, v);CHKERRQ(ierr); 184 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 185 } else { 186 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 187 } 188 PetscFunctionReturn(0); 189 } 190 191 #undef __FUNCT__ 192 #define __FUNCT__ "DMPlexView_Ascii" 193 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 194 { 195 DM_Plex *mesh = (DM_Plex*) dm->data; 196 DM cdm; 197 DMLabel markers; 198 PetscSection coordSection; 199 Vec coordinates; 200 PetscViewerFormat format; 201 PetscErrorCode ierr; 202 203 PetscFunctionBegin; 204 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 205 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 206 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 207 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 208 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 209 const char *name; 210 PetscInt maxConeSize, maxSupportSize; 211 PetscInt pStart, pEnd, p; 212 PetscMPIInt rank, size; 213 214 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 215 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 216 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 217 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 218 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 220 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 221 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 222 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 223 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 224 for (p = pStart; p < pEnd; ++p) { 225 PetscInt dof, off, s; 226 227 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 228 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 229 for (s = off; s < off+dof; ++s) { 230 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 231 } 232 } 233 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 234 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 235 for (p = pStart; p < pEnd; ++p) { 236 PetscInt dof, off, c; 237 238 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 239 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 240 for (c = off; c < off+dof; ++c) { 241 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 242 } 243 } 244 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 245 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 246 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 247 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 248 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 249 if (size > 1) { 250 PetscSF sf; 251 252 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 253 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 254 } 255 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 256 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 257 const char *name; 258 const char *colors[3] = {"red", "blue", "green"}; 259 const int numColors = 3; 260 PetscReal scale = 2.0; 261 PetscScalar *coords; 262 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 263 PetscMPIInt rank, size; 264 265 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 266 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 267 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 268 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 269 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 270 ierr = PetscViewerASCIIPrintf(viewer, "\ 271 \\documentclass[crop,multi=false]{standalone}\n\n\ 272 \\usepackage{tikz}\n\ 273 \\usepackage{pgflibraryshapes}\n\ 274 \\usetikzlibrary{backgrounds}\n\ 275 \\usetikzlibrary{arrows}\n\ 276 \\begin{document}\n\ 277 \\section{%s}\n\ 278 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 279 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 280 for (p = 0; p < size; ++p) { 281 if (p > 0 && p == size-1) { 282 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 283 } else if (p > 0) { 284 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 285 } 286 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 287 } 288 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 289 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 290 /* Plot vertices */ 291 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 292 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 293 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 294 for (v = vStart; v < vEnd; ++v) { 295 PetscInt off, dof, d; 296 297 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 298 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 299 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 300 for (d = 0; d < dof; ++d) { 301 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 302 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)(scale*PetscRealPart(coords[off+d])));CHKERRQ(ierr); 303 } 304 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 305 } 306 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 307 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 308 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 309 /* Plot edges */ 310 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 311 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 312 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 313 for (e = eStart; e < eEnd; ++e) { 314 const PetscInt *cone; 315 PetscInt coneSize, offA, offB, dof, d; 316 317 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 318 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 319 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 320 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 321 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 322 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 323 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 324 for (d = 0; d < dof; ++d) { 325 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 326 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)(scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d])));CHKERRQ(ierr); 327 } 328 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 329 } 330 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 331 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 332 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 333 /* Plot cells */ 334 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 335 for (c = cStart; c < cEnd; ++c) { 336 PetscInt *closure = NULL; 337 PetscInt closureSize, firstPoint = -1; 338 339 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 340 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 341 for (p = 0; p < closureSize*2; p += 2) { 342 const PetscInt point = closure[p]; 343 344 if ((point < vStart) || (point >= vEnd)) continue; 345 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 346 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 347 if (firstPoint < 0) firstPoint = point; 348 } 349 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 350 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 351 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 352 } 353 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 354 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 355 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 356 } else { 357 MPI_Comm comm; 358 PetscInt *sizes, *hybsizes; 359 PetscInt locDepth, depth, dim, d, pMax[4]; 360 PetscInt pStart, pEnd, p; 361 PetscInt numLabels, l; 362 const char *name; 363 PetscMPIInt size; 364 365 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 366 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 367 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 368 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 369 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimensions:\n", name, dim);CHKERRQ(ierr);} 370 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr);} 371 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 372 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 373 ierr = DMPlexGetHybridBounds(dm, &pMax[depth], &pMax[depth-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 374 ierr = PetscMalloc2(size,&sizes,size,&hybsizes);CHKERRQ(ierr); 375 if (depth == 1) { 376 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 377 pEnd = pEnd - pStart; 378 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 379 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 380 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 381 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 382 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 383 pEnd = pEnd - pStart; 384 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 385 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 386 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 387 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 388 } else { 389 for (d = 0; d <= dim; d++) { 390 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 391 pEnd -= pStart; 392 pMax[d] -= pStart; 393 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 394 ierr = MPI_Gather(&pMax[d], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 395 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 396 for (p = 0; p < size; ++p) { 397 if (hybsizes[p] >= 0) {ierr = PetscViewerASCIIPrintf(viewer, " %D (%D)", sizes[p], sizes[p] - hybsizes[p]);CHKERRQ(ierr);} 398 else {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 399 } 400 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 401 } 402 } 403 ierr = PetscFree2(sizes,hybsizes);CHKERRQ(ierr); 404 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 405 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 406 for (l = 0; l < numLabels; ++l) { 407 DMLabel label; 408 const char *name; 409 IS valueIS; 410 const PetscInt *values; 411 PetscInt numValues, v; 412 413 ierr = DMPlexGetLabelName(dm, l, &name);CHKERRQ(ierr); 414 ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); 415 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 416 ierr = PetscViewerASCIIPrintf(viewer, " %s: %d strata of sizes (", name, numValues);CHKERRQ(ierr); 417 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 418 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 419 for (v = 0; v < numValues; ++v) { 420 PetscInt size; 421 422 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 423 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 424 ierr = PetscViewerASCIIPrintf(viewer, "%d", size);CHKERRQ(ierr); 425 } 426 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 427 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 428 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 429 } 430 } 431 PetscFunctionReturn(0); 432 } 433 434 #if defined(PETSC_HAVE_HDF5) 435 #undef __FUNCT__ 436 #define __FUNCT__ "DMPlexView_HDF5" 437 /* We only write cells and vertices. Does this screw up parallel reading? */ 438 PetscErrorCode DMPlexView_HDF5(DM dm, PetscViewer viewer) 439 { 440 DM cdm; 441 Vec coordinates, newcoords; 442 Vec coneVec, cellVec; 443 IS globalVertexNumbers; 444 const PetscInt *gvertex; 445 PetscScalar *sizes, *vertices; 446 PetscReal lengthScale; 447 const char *label = NULL; 448 PetscInt labelId = 0, dim; 449 PetscInt vStart, vEnd, v, cellHeight, cStart, cEnd, cMax, cell, conesSize = 0, numCornersLocal = 0, numCorners; 450 PetscErrorCode ierr; 451 452 PetscFunctionBegin; 453 /* Write coordinates */ 454 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 455 ierr = DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale);CHKERRQ(ierr); 456 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 457 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 458 ierr = VecDuplicate(coordinates, &newcoords);CHKERRQ(ierr); 459 ierr = PetscObjectSetName((PetscObject) newcoords, "vertices");CHKERRQ(ierr); 460 ierr = VecCopy(coordinates, newcoords);CHKERRQ(ierr); 461 ierr = VecScale(newcoords, lengthScale);CHKERRQ(ierr); 462 /* Use the local version to bypass the default group setting */ 463 ierr = PetscViewerHDF5PushGroup(viewer, "/geometry");CHKERRQ(ierr); 464 ierr = VecView(newcoords, viewer);CHKERRQ(ierr); 465 ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr); 466 ierr = VecDestroy(&newcoords);CHKERRQ(ierr); 467 /* Write toplogy */ 468 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 469 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 470 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 471 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 472 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 473 474 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &coneVec);CHKERRQ(ierr); 475 ierr = VecSetSizes(coneVec, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 476 ierr = VecSetBlockSize(coneVec, 1);CHKERRQ(ierr); 477 ierr = VecSetFromOptions(coneVec);CHKERRQ(ierr); 478 ierr = PetscObjectSetName((PetscObject) coneVec, "coneSize");CHKERRQ(ierr); 479 ierr = VecGetArray(coneVec, &sizes);CHKERRQ(ierr); 480 for (cell = cStart; cell < cEnd; ++cell) { 481 PetscInt *closure = NULL; 482 PetscInt closureSize, v, Nc = 0; 483 484 if (label) { 485 PetscInt value; 486 ierr = DMPlexGetLabelValue(dm, label, cell, &value);CHKERRQ(ierr); 487 if (value == labelId) continue; 488 } 489 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 490 for (v = 0; v < closureSize*2; v += 2) { 491 if ((closure[v] >= vStart) && (closure[v] < vEnd)) ++Nc; 492 } 493 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 494 conesSize += Nc; 495 if (!numCornersLocal) numCornersLocal = Nc; 496 else if (numCornersLocal != Nc) numCornersLocal = 1; 497 } 498 ierr = VecRestoreArray(coneVec, &sizes);CHKERRQ(ierr); 499 ierr = MPI_Allreduce(&numCornersLocal, &numCorners, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 500 if (numCornersLocal && numCornersLocal != numCorners) numCorners = 1; 501 502 ierr = DMPlexGetVertexNumbering(dm, &globalVertexNumbers);CHKERRQ(ierr); 503 ierr = ISGetIndices(globalVertexNumbers, &gvertex);CHKERRQ(ierr); 504 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &cellVec);CHKERRQ(ierr); 505 ierr = VecSetSizes(cellVec, conesSize, PETSC_DETERMINE);CHKERRQ(ierr); 506 ierr = VecSetBlockSize(cellVec, numCorners);CHKERRQ(ierr); 507 ierr = VecSetFromOptions(cellVec);CHKERRQ(ierr); 508 ierr = PetscObjectSetName((PetscObject) cellVec, "cells");CHKERRQ(ierr); 509 ierr = VecGetArray(cellVec, &vertices);CHKERRQ(ierr); 510 for (cell = cStart, v = 0; cell < cEnd; ++cell) { 511 PetscInt *closure = NULL; 512 PetscInt closureSize, Nc = 0, p; 513 514 if (label) { 515 PetscInt value; 516 ierr = DMPlexGetLabelValue(dm, label, cell, &value);CHKERRQ(ierr); 517 if (value == labelId) continue; 518 } 519 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 520 for (p = 0; p < closureSize*2; p += 2) { 521 if ((closure[p] >= vStart) && (closure[p] < vEnd)) { 522 closure[Nc++] = closure[p]; 523 } 524 } 525 ierr = DMPlexInvertCell(dim, Nc, closure);CHKERRQ(ierr); 526 for (p = 0; p < Nc; ++p) { 527 const PetscInt gv = gvertex[closure[p] - vStart]; 528 vertices[v++] = gv < 0 ? -(gv+1) : gv; 529 } 530 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 531 } 532 if (v != conesSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of cell vertices %d != %d", v, conesSize); 533 ierr = VecRestoreArray(cellVec, &vertices);CHKERRQ(ierr); 534 ierr = PetscViewerHDF5PushGroup(viewer, "/topology");CHKERRQ(ierr); 535 ierr = VecView(cellVec, viewer);CHKERRQ(ierr); 536 if (numCorners == 1) { 537 ierr = VecView(coneVec, viewer);CHKERRQ(ierr); 538 } else { 539 ierr = PetscViewerHDF5WriteAttribute(viewer, "/topology/cells", "cell_corners", PETSC_INT, (void *) &numCorners);CHKERRQ(ierr); 540 } 541 ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr); 542 ierr = VecDestroy(&cellVec);CHKERRQ(ierr); 543 ierr = VecDestroy(&coneVec);CHKERRQ(ierr); 544 ierr = ISRestoreIndices(globalVertexNumbers, &gvertex);CHKERRQ(ierr); 545 546 ierr = PetscViewerHDF5WriteAttribute(viewer, "/topology/cells", "cell_dim", PETSC_INT, (void *) &dim);CHKERRQ(ierr); 547 PetscFunctionReturn(0); 548 } 549 #endif 550 551 #undef __FUNCT__ 552 #define __FUNCT__ "DMView_Plex" 553 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 554 { 555 PetscBool iascii, ishdf5; 556 PetscErrorCode ierr; 557 558 PetscFunctionBegin; 559 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 560 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 561 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 562 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 563 if (iascii) { 564 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 565 } else if (ishdf5) { 566 #if defined(PETSC_HAVE_HDF5) 567 ierr = DMPlexView_HDF5(dm, viewer);CHKERRQ(ierr); 568 #else 569 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 570 #endif 571 } 572 PetscFunctionReturn(0); 573 } 574 575 #if defined(PETSC_HAVE_HDF5) 576 #undef __FUNCT__ 577 #define __FUNCT__ "DMPlexLoad_HDF5" 578 /* The first version will read everything onto proc 0, letting the user distribute 579 The next will create a naive partition, and then rebalance after reading 580 */ 581 PetscErrorCode DMPlexLoad_HDF5(DM dm, PetscViewer viewer) 582 { 583 PetscSection coordSection; 584 Vec coordinates; 585 Vec cellVec; 586 PetscScalar *cells; 587 PetscReal lengthScale; 588 PetscInt *cone; 589 PetscInt dim, spatialDim, numVertices, v, numCorners, numCells, cell, c; 590 PetscErrorCode ierr; 591 592 PetscFunctionBegin; 593 /* Read geometry */ 594 ierr = PetscViewerHDF5PushGroup(viewer, "/geometry");CHKERRQ(ierr); 595 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &coordinates);CHKERRQ(ierr); 596 ierr = PetscObjectSetName((PetscObject) coordinates, "vertices");CHKERRQ(ierr); 597 ierr = VecLoad(coordinates, viewer);CHKERRQ(ierr); 598 ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr); 599 ierr = DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale);CHKERRQ(ierr); 600 ierr = VecScale(coordinates, 1.0/lengthScale);CHKERRQ(ierr); 601 ierr = VecGetSize(coordinates, &numVertices);CHKERRQ(ierr); 602 ierr = VecGetBlockSize(coordinates, &spatialDim);CHKERRQ(ierr); 603 numVertices /= spatialDim; 604 /* Read toplogy */ 605 ierr = PetscViewerHDF5ReadAttribute(viewer, "/topology/cells", "cell_dim", PETSC_INT, (void *) &dim);CHKERRQ(ierr); 606 ierr = DMPlexSetDimension(dm, dim);CHKERRQ(ierr); 607 /* TODO Check for coneSize vector rather than this attribute */ 608 ierr = PetscViewerHDF5ReadAttribute(viewer, "/topology/cells", "cell_corners", PETSC_INT, (void *) &numCorners);CHKERRQ(ierr); 609 ierr = PetscViewerHDF5PushGroup(viewer, "/topology");CHKERRQ(ierr); 610 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &cellVec);CHKERRQ(ierr); 611 ierr = VecSetBlockSize(cellVec, numCorners);CHKERRQ(ierr); 612 ierr = PetscObjectSetName((PetscObject) cellVec, "cells");CHKERRQ(ierr); 613 ierr = VecLoad(cellVec, viewer);CHKERRQ(ierr); 614 ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr); 615 ierr = VecGetSize(cellVec, &numCells);CHKERRQ(ierr); 616 numCells /= numCorners; 617 /* Create Plex */ 618 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 619 for (cell = 0; cell < numCells; ++cell) {ierr = DMPlexSetConeSize(dm, cell, numCorners);CHKERRQ(ierr);} 620 ierr = DMSetUp(dm);CHKERRQ(ierr); 621 ierr = PetscMalloc1(numCorners,&cone);CHKERRQ(ierr); 622 ierr = VecGetArray(cellVec, &cells);CHKERRQ(ierr); 623 for (cell = 0; cell < numCells; ++cell) { 624 for (c = 0; c < numCorners; ++c) {cone[c] = numCells + cells[cell*numCorners+c];} 625 ierr = DMPlexSetCone(dm, cell, cone);CHKERRQ(ierr); 626 } 627 ierr = VecRestoreArray(cellVec, &cells);CHKERRQ(ierr); 628 ierr = PetscFree(cone);CHKERRQ(ierr); 629 ierr = VecDestroy(&cellVec);CHKERRQ(ierr); 630 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 631 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 632 /* Create coordinates */ 633 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 634 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 635 ierr = PetscSectionSetFieldComponents(coordSection, 0, spatialDim);CHKERRQ(ierr); 636 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVertices);CHKERRQ(ierr); 637 for (v = numCells; v < numCells+numVertices; ++v) { 638 ierr = PetscSectionSetDof(coordSection, v, spatialDim);CHKERRQ(ierr); 639 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spatialDim);CHKERRQ(ierr); 640 } 641 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 642 ierr = DMSetCoordinates(dm, coordinates);CHKERRQ(ierr); 643 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 644 /* TODO Labels*/ 645 PetscFunctionReturn(0); 646 } 647 #endif 648 649 #undef __FUNCT__ 650 #define __FUNCT__ "DMLoad_Plex" 651 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 652 { 653 PetscBool isbinary, ishdf5; 654 PetscErrorCode ierr; 655 656 PetscFunctionBegin; 657 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 658 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 659 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 660 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 661 if (isbinary) {SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Do not yet support binary viewers");} 662 else if (ishdf5) { 663 DM odm; 664 #if defined(PETSC_HAVE_HDF5) 665 ierr = DMCreate(PetscObjectComm((PetscObject) dm), &odm);CHKERRQ(ierr); 666 ierr = DMSetType(odm, DMPLEX);CHKERRQ(ierr); 667 ierr = DMPlexLoad_HDF5(odm, viewer);CHKERRQ(ierr); 668 ierr = DMPlexInterpolate(odm, &dm);CHKERRQ(ierr); 669 ierr = DMPlexCopyCoordinates(odm, dm);CHKERRQ(ierr); 670 ierr = DMDestroy(&odm);CHKERRQ(ierr); 671 #else 672 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 673 #endif 674 } 675 PetscFunctionReturn(0); 676 } 677 678 #undef __FUNCT__ 679 #define __FUNCT__ "BoundaryDestroy" 680 static PetscErrorCode BoundaryDestroy(DMBoundary *boundary) 681 { 682 DMBoundary b, next; 683 PetscErrorCode ierr; 684 685 PetscFunctionBeginUser; 686 if (!boundary) PetscFunctionReturn(0); 687 b = *boundary; 688 *boundary = NULL; 689 for (; b; b = next) { 690 next = b->next; 691 ierr = PetscFree(b->ids);CHKERRQ(ierr); 692 ierr = PetscFree(b->name);CHKERRQ(ierr); 693 ierr = PetscFree(b);CHKERRQ(ierr); 694 } 695 PetscFunctionReturn(0); 696 } 697 698 #undef __FUNCT__ 699 #define __FUNCT__ "DMDestroy_Plex" 700 PetscErrorCode DMDestroy_Plex(DM dm) 701 { 702 DM_Plex *mesh = (DM_Plex*) dm->data; 703 DMLabel next = mesh->labels; 704 PetscErrorCode ierr; 705 706 PetscFunctionBegin; 707 if (--mesh->refct > 0) PetscFunctionReturn(0); 708 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 709 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 710 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 711 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 712 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 713 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 714 while (next) { 715 DMLabel tmp = next->next; 716 717 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 718 next = tmp; 719 } 720 ierr = DMDestroy(&mesh->coarseMesh);CHKERRQ(ierr); 721 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 722 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 723 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 724 ierr = BoundaryDestroy(&mesh->boundary);CHKERRQ(ierr); 725 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 726 ierr = PetscFree(mesh);CHKERRQ(ierr); 727 PetscFunctionReturn(0); 728 } 729 730 #undef __FUNCT__ 731 #define __FUNCT__ "DMCreateMatrix_Plex" 732 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 733 { 734 PetscSection section, sectionGlobal; 735 PetscInt bs = -1; 736 PetscInt localSize; 737 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock; 738 PetscErrorCode ierr; 739 MatType mtype; 740 741 PetscFunctionBegin; 742 ierr = MatInitializePackage();CHKERRQ(ierr); 743 mtype = dm->mattype; 744 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 745 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 746 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 747 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 748 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 749 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 750 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 751 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 752 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 753 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 754 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 755 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 756 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 757 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 758 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 759 if (!isShell) { 760 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 761 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 762 763 if (bs < 0) { 764 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 765 PetscInt pStart, pEnd, p, dof, cdof; 766 767 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 768 for (p = pStart; p < pEnd; ++p) { 769 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 770 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 771 if (dof-cdof) { 772 if (bs < 0) { 773 bs = dof-cdof; 774 } else if (bs != dof-cdof) { 775 /* Layout does not admit a pointwise block size */ 776 bs = 1; 777 break; 778 } 779 } 780 } 781 /* Must have same blocksize on all procs (some might have no points) */ 782 bsLocal = bs; 783 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 784 bsLocal = bs < 0 ? bsMax : bs; 785 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 786 if (bsMin != bsMax) { 787 bs = 1; 788 } else { 789 bs = bsMax; 790 } 791 } else { 792 bs = 1; 793 } 794 } 795 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 796 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 797 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 798 } 799 PetscFunctionReturn(0); 800 } 801 802 #undef __FUNCT__ 803 #define __FUNCT__ "DMPlexGetDimension" 804 /*@ 805 DMPlexGetDimension - Return the topological mesh dimension 806 807 Not collective 808 809 Input Parameter: 810 . mesh - The DMPlex 811 812 Output Parameter: 813 . dim - The topological mesh dimension 814 815 Level: beginner 816 817 .seealso: DMPlexCreate() 818 @*/ 819 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 820 { 821 DM_Plex *mesh = (DM_Plex*) dm->data; 822 823 PetscFunctionBegin; 824 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 825 PetscValidPointer(dim, 2); 826 *dim = mesh->dim; 827 PetscFunctionReturn(0); 828 } 829 830 #undef __FUNCT__ 831 #define __FUNCT__ "DMPlexSetDimension" 832 /*@ 833 DMPlexSetDimension - Set the topological mesh dimension 834 835 Collective on mesh 836 837 Input Parameters: 838 + mesh - The DMPlex 839 - dim - The topological mesh dimension 840 841 Level: beginner 842 843 .seealso: DMPlexCreate() 844 @*/ 845 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 846 { 847 DM_Plex *mesh = (DM_Plex*) dm->data; 848 849 PetscFunctionBegin; 850 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 851 PetscValidLogicalCollectiveInt(dm, dim, 2); 852 mesh->dim = dim; 853 PetscFunctionReturn(0); 854 } 855 856 #undef __FUNCT__ 857 #define __FUNCT__ "DMPlexGetChart" 858 /*@ 859 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 860 861 Not collective 862 863 Input Parameter: 864 . mesh - The DMPlex 865 866 Output Parameters: 867 + pStart - The first mesh point 868 - pEnd - The upper bound for mesh points 869 870 Level: beginner 871 872 .seealso: DMPlexCreate(), DMPlexSetChart() 873 @*/ 874 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 875 { 876 DM_Plex *mesh = (DM_Plex*) dm->data; 877 PetscErrorCode ierr; 878 879 PetscFunctionBegin; 880 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 881 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 882 PetscFunctionReturn(0); 883 } 884 885 #undef __FUNCT__ 886 #define __FUNCT__ "DMPlexSetChart" 887 /*@ 888 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 889 890 Not collective 891 892 Input Parameters: 893 + mesh - The DMPlex 894 . pStart - The first mesh point 895 - pEnd - The upper bound for mesh points 896 897 Output Parameters: 898 899 Level: beginner 900 901 .seealso: DMPlexCreate(), DMPlexGetChart() 902 @*/ 903 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 904 { 905 DM_Plex *mesh = (DM_Plex*) dm->data; 906 PetscErrorCode ierr; 907 908 PetscFunctionBegin; 909 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 910 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 911 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 912 PetscFunctionReturn(0); 913 } 914 915 #undef __FUNCT__ 916 #define __FUNCT__ "DMPlexGetConeSize" 917 /*@ 918 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 919 920 Not collective 921 922 Input Parameters: 923 + mesh - The DMPlex 924 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 925 926 Output Parameter: 927 . size - The cone size for point p 928 929 Level: beginner 930 931 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 932 @*/ 933 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 934 { 935 DM_Plex *mesh = (DM_Plex*) dm->data; 936 PetscErrorCode ierr; 937 938 PetscFunctionBegin; 939 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 940 PetscValidPointer(size, 3); 941 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 942 PetscFunctionReturn(0); 943 } 944 945 #undef __FUNCT__ 946 #define __FUNCT__ "DMPlexSetConeSize" 947 /*@ 948 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 949 950 Not collective 951 952 Input Parameters: 953 + mesh - The DMPlex 954 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 955 - size - The cone size for point p 956 957 Output Parameter: 958 959 Note: 960 This should be called after DMPlexSetChart(). 961 962 Level: beginner 963 964 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 965 @*/ 966 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 967 { 968 DM_Plex *mesh = (DM_Plex*) dm->data; 969 PetscErrorCode ierr; 970 971 PetscFunctionBegin; 972 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 973 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 974 975 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 976 PetscFunctionReturn(0); 977 } 978 979 #undef __FUNCT__ 980 #define __FUNCT__ "DMPlexGetCone" 981 /*@C 982 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 983 984 Not collective 985 986 Input Parameters: 987 + mesh - The DMPlex 988 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 989 990 Output Parameter: 991 . cone - An array of points which are on the in-edges for point p 992 993 Level: beginner 994 995 Fortran Notes: 996 Since it returns an array, this routine is only available in Fortran 90, and you must 997 include petsc.h90 in your code. 998 999 You must also call DMPlexRestoreCone() after you finish using the returned array. 1000 1001 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1002 @*/ 1003 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1004 { 1005 DM_Plex *mesh = (DM_Plex*) dm->data; 1006 PetscInt off; 1007 PetscErrorCode ierr; 1008 1009 PetscFunctionBegin; 1010 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1011 PetscValidPointer(cone, 3); 1012 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1013 *cone = &mesh->cones[off]; 1014 PetscFunctionReturn(0); 1015 } 1016 1017 #undef __FUNCT__ 1018 #define __FUNCT__ "DMPlexSetCone" 1019 /*@ 1020 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1021 1022 Not collective 1023 1024 Input Parameters: 1025 + mesh - The DMPlex 1026 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1027 - cone - An array of points which are on the in-edges for point p 1028 1029 Output Parameter: 1030 1031 Note: 1032 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1033 1034 Level: beginner 1035 1036 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1037 @*/ 1038 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1039 { 1040 DM_Plex *mesh = (DM_Plex*) dm->data; 1041 PetscInt pStart, pEnd; 1042 PetscInt dof, off, c; 1043 PetscErrorCode ierr; 1044 1045 PetscFunctionBegin; 1046 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1047 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1048 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1049 if (dof) PetscValidPointer(cone, 3); 1050 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1051 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); 1052 for (c = 0; c < dof; ++c) { 1053 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); 1054 mesh->cones[off+c] = cone[c]; 1055 } 1056 PetscFunctionReturn(0); 1057 } 1058 1059 #undef __FUNCT__ 1060 #define __FUNCT__ "DMPlexGetConeOrientation" 1061 /*@C 1062 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1063 1064 Not collective 1065 1066 Input Parameters: 1067 + mesh - The DMPlex 1068 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1069 1070 Output Parameter: 1071 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1072 integer giving the prescription for cone traversal. If it is negative, the cone is 1073 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1074 the index of the cone point on which to start. 1075 1076 Level: beginner 1077 1078 Fortran Notes: 1079 Since it returns an array, this routine is only available in Fortran 90, and you must 1080 include petsc.h90 in your code. 1081 1082 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 1083 1084 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1085 @*/ 1086 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1087 { 1088 DM_Plex *mesh = (DM_Plex*) dm->data; 1089 PetscInt off; 1090 PetscErrorCode ierr; 1091 1092 PetscFunctionBegin; 1093 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1094 #if defined(PETSC_USE_DEBUG) 1095 { 1096 PetscInt dof; 1097 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1098 if (dof) PetscValidPointer(coneOrientation, 3); 1099 } 1100 #endif 1101 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1102 1103 *coneOrientation = &mesh->coneOrientations[off]; 1104 PetscFunctionReturn(0); 1105 } 1106 1107 #undef __FUNCT__ 1108 #define __FUNCT__ "DMPlexSetConeOrientation" 1109 /*@ 1110 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1111 1112 Not collective 1113 1114 Input Parameters: 1115 + mesh - The DMPlex 1116 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1117 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1118 integer giving the prescription for cone traversal. If it is negative, the cone is 1119 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1120 the index of the cone point on which to start. 1121 1122 Output Parameter: 1123 1124 Note: 1125 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1126 1127 Level: beginner 1128 1129 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1130 @*/ 1131 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1132 { 1133 DM_Plex *mesh = (DM_Plex*) dm->data; 1134 PetscInt pStart, pEnd; 1135 PetscInt dof, off, c; 1136 PetscErrorCode ierr; 1137 1138 PetscFunctionBegin; 1139 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1140 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1141 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1142 if (dof) PetscValidPointer(coneOrientation, 3); 1143 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1144 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); 1145 for (c = 0; c < dof; ++c) { 1146 PetscInt cdof, o = coneOrientation[c]; 1147 1148 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1149 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); 1150 mesh->coneOrientations[off+c] = o; 1151 } 1152 PetscFunctionReturn(0); 1153 } 1154 1155 #undef __FUNCT__ 1156 #define __FUNCT__ "DMPlexInsertCone" 1157 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1158 { 1159 DM_Plex *mesh = (DM_Plex*) dm->data; 1160 PetscInt pStart, pEnd; 1161 PetscInt dof, off; 1162 PetscErrorCode ierr; 1163 1164 PetscFunctionBegin; 1165 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1166 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1167 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); 1168 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); 1169 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1170 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1171 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); 1172 mesh->cones[off+conePos] = conePoint; 1173 PetscFunctionReturn(0); 1174 } 1175 1176 #undef __FUNCT__ 1177 #define __FUNCT__ "DMPlexInsertConeOrientation" 1178 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 1179 { 1180 DM_Plex *mesh = (DM_Plex*) dm->data; 1181 PetscInt pStart, pEnd; 1182 PetscInt dof, off; 1183 PetscErrorCode ierr; 1184 1185 PetscFunctionBegin; 1186 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1187 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1188 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); 1189 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1190 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1191 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); 1192 mesh->coneOrientations[off+conePos] = coneOrientation; 1193 PetscFunctionReturn(0); 1194 } 1195 1196 #undef __FUNCT__ 1197 #define __FUNCT__ "DMPlexGetSupportSize" 1198 /*@ 1199 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1200 1201 Not collective 1202 1203 Input Parameters: 1204 + mesh - The DMPlex 1205 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1206 1207 Output Parameter: 1208 . size - The support size for point p 1209 1210 Level: beginner 1211 1212 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1213 @*/ 1214 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1215 { 1216 DM_Plex *mesh = (DM_Plex*) dm->data; 1217 PetscErrorCode ierr; 1218 1219 PetscFunctionBegin; 1220 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1221 PetscValidPointer(size, 3); 1222 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1223 PetscFunctionReturn(0); 1224 } 1225 1226 #undef __FUNCT__ 1227 #define __FUNCT__ "DMPlexSetSupportSize" 1228 /*@ 1229 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1230 1231 Not collective 1232 1233 Input Parameters: 1234 + mesh - The DMPlex 1235 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1236 - size - The support size for point p 1237 1238 Output Parameter: 1239 1240 Note: 1241 This should be called after DMPlexSetChart(). 1242 1243 Level: beginner 1244 1245 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1246 @*/ 1247 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1248 { 1249 DM_Plex *mesh = (DM_Plex*) dm->data; 1250 PetscErrorCode ierr; 1251 1252 PetscFunctionBegin; 1253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1254 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1255 1256 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1257 PetscFunctionReturn(0); 1258 } 1259 1260 #undef __FUNCT__ 1261 #define __FUNCT__ "DMPlexGetSupport" 1262 /*@C 1263 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1264 1265 Not collective 1266 1267 Input Parameters: 1268 + mesh - The DMPlex 1269 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1270 1271 Output Parameter: 1272 . support - An array of points which are on the out-edges for point p 1273 1274 Level: beginner 1275 1276 Fortran Notes: 1277 Since it returns an array, this routine is only available in Fortran 90, and you must 1278 include petsc.h90 in your code. 1279 1280 You must also call DMPlexRestoreSupport() after you finish using the returned array. 1281 1282 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1283 @*/ 1284 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1285 { 1286 DM_Plex *mesh = (DM_Plex*) dm->data; 1287 PetscInt off; 1288 PetscErrorCode ierr; 1289 1290 PetscFunctionBegin; 1291 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1292 PetscValidPointer(support, 3); 1293 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1294 *support = &mesh->supports[off]; 1295 PetscFunctionReturn(0); 1296 } 1297 1298 #undef __FUNCT__ 1299 #define __FUNCT__ "DMPlexSetSupport" 1300 /*@ 1301 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1302 1303 Not collective 1304 1305 Input Parameters: 1306 + mesh - The DMPlex 1307 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1308 - support - An array of points which are on the in-edges for point p 1309 1310 Output Parameter: 1311 1312 Note: 1313 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1314 1315 Level: beginner 1316 1317 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1318 @*/ 1319 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1320 { 1321 DM_Plex *mesh = (DM_Plex*) dm->data; 1322 PetscInt pStart, pEnd; 1323 PetscInt dof, off, c; 1324 PetscErrorCode ierr; 1325 1326 PetscFunctionBegin; 1327 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1328 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1329 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1330 if (dof) PetscValidPointer(support, 3); 1331 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1332 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); 1333 for (c = 0; c < dof; ++c) { 1334 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); 1335 mesh->supports[off+c] = support[c]; 1336 } 1337 PetscFunctionReturn(0); 1338 } 1339 1340 #undef __FUNCT__ 1341 #define __FUNCT__ "DMPlexInsertSupport" 1342 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1343 { 1344 DM_Plex *mesh = (DM_Plex*) dm->data; 1345 PetscInt pStart, pEnd; 1346 PetscInt dof, off; 1347 PetscErrorCode ierr; 1348 1349 PetscFunctionBegin; 1350 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1351 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1352 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1353 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1354 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); 1355 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); 1356 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); 1357 mesh->supports[off+supportPos] = supportPoint; 1358 PetscFunctionReturn(0); 1359 } 1360 1361 #undef __FUNCT__ 1362 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1363 /*@C 1364 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1365 1366 Not collective 1367 1368 Input Parameters: 1369 + mesh - The DMPlex 1370 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1371 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1372 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1373 1374 Output Parameters: 1375 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1376 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1377 1378 Note: 1379 If using internal storage (points is NULL on input), each call overwrites the last output. 1380 1381 Fortran Notes: 1382 Since it returns an array, this routine is only available in Fortran 90, and you must 1383 include petsc.h90 in your code. 1384 1385 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1386 1387 Level: beginner 1388 1389 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1390 @*/ 1391 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1392 { 1393 DM_Plex *mesh = (DM_Plex*) dm->data; 1394 PetscInt *closure, *fifo; 1395 const PetscInt *tmp = NULL, *tmpO = NULL; 1396 PetscInt tmpSize, t; 1397 PetscInt depth = 0, maxSize; 1398 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1399 PetscErrorCode ierr; 1400 1401 PetscFunctionBegin; 1402 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1403 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1404 /* This is only 1-level */ 1405 if (useCone) { 1406 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1407 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1408 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1409 } else { 1410 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1411 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1412 } 1413 if (depth == 1) { 1414 if (*points) { 1415 closure = *points; 1416 } else { 1417 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 1418 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1419 } 1420 closure[0] = p; closure[1] = 0; 1421 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 1422 closure[closureSize] = tmp[t]; 1423 closure[closureSize+1] = tmpO ? tmpO[t] : 0; 1424 } 1425 if (numPoints) *numPoints = closureSize/2; 1426 if (points) *points = closure; 1427 PetscFunctionReturn(0); 1428 } 1429 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)),depth+1); 1430 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1431 if (*points) { 1432 closure = *points; 1433 } else { 1434 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1435 } 1436 closure[0] = p; closure[1] = 0; 1437 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1438 const PetscInt cp = tmp[t]; 1439 const PetscInt co = tmpO ? tmpO[t] : 0; 1440 1441 closure[closureSize] = cp; 1442 closure[closureSize+1] = co; 1443 fifo[fifoSize] = cp; 1444 fifo[fifoSize+1] = co; 1445 } 1446 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 1447 while (fifoSize - fifoStart) { 1448 const PetscInt q = fifo[fifoStart]; 1449 const PetscInt o = fifo[fifoStart+1]; 1450 const PetscInt rev = o >= 0 ? 0 : 1; 1451 const PetscInt off = rev ? -(o+1) : o; 1452 1453 if (useCone) { 1454 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1455 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1456 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1457 } else { 1458 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1459 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1460 tmpO = NULL; 1461 } 1462 for (t = 0; t < tmpSize; ++t) { 1463 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1464 const PetscInt cp = tmp[i]; 1465 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 1466 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 1467 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 1468 PetscInt co = tmpO ? tmpO[i] : 0; 1469 PetscInt c; 1470 1471 if (rev) { 1472 PetscInt childSize, coff; 1473 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1474 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1475 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1476 } 1477 /* Check for duplicate */ 1478 for (c = 0; c < closureSize; c += 2) { 1479 if (closure[c] == cp) break; 1480 } 1481 if (c == closureSize) { 1482 closure[closureSize] = cp; 1483 closure[closureSize+1] = co; 1484 fifo[fifoSize] = cp; 1485 fifo[fifoSize+1] = co; 1486 closureSize += 2; 1487 fifoSize += 2; 1488 } 1489 } 1490 fifoStart += 2; 1491 } 1492 if (numPoints) *numPoints = closureSize/2; 1493 if (points) *points = closure; 1494 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1495 PetscFunctionReturn(0); 1496 } 1497 1498 #undef __FUNCT__ 1499 #define __FUNCT__ "DMPlexGetTransitiveClosure_Internal" 1500 /*@C 1501 DMPlexGetTransitiveClosure_Internal - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG with a specified initial orientation 1502 1503 Not collective 1504 1505 Input Parameters: 1506 + mesh - The DMPlex 1507 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1508 . orientation - The orientation of the point 1509 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1510 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1511 1512 Output Parameters: 1513 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1514 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1515 1516 Note: 1517 If using internal storage (points is NULL on input), each call overwrites the last output. 1518 1519 Fortran Notes: 1520 Since it returns an array, this routine is only available in Fortran 90, and you must 1521 include petsc.h90 in your code. 1522 1523 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1524 1525 Level: beginner 1526 1527 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1528 @*/ 1529 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1530 { 1531 DM_Plex *mesh = (DM_Plex*) dm->data; 1532 PetscInt *closure, *fifo; 1533 const PetscInt *tmp = NULL, *tmpO = NULL; 1534 PetscInt tmpSize, t; 1535 PetscInt depth = 0, maxSize; 1536 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1537 PetscErrorCode ierr; 1538 1539 PetscFunctionBegin; 1540 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1541 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1542 /* This is only 1-level */ 1543 if (useCone) { 1544 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1545 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1546 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1547 } else { 1548 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1549 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1550 } 1551 if (depth == 1) { 1552 if (*points) { 1553 closure = *points; 1554 } else { 1555 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 1556 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1557 } 1558 closure[0] = p; closure[1] = ornt; 1559 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 1560 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 1561 closure[closureSize] = tmp[i]; 1562 closure[closureSize+1] = tmpO ? tmpO[i] : 0; 1563 } 1564 if (numPoints) *numPoints = closureSize/2; 1565 if (points) *points = closure; 1566 PetscFunctionReturn(0); 1567 } 1568 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)),depth+1); 1569 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1570 if (*points) { 1571 closure = *points; 1572 } else { 1573 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1574 } 1575 closure[0] = p; closure[1] = ornt; 1576 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1577 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 1578 const PetscInt cp = tmp[i]; 1579 PetscInt co = tmpO ? tmpO[i] : 0; 1580 1581 if (ornt < 0) { 1582 PetscInt childSize, coff; 1583 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1584 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1585 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1586 } 1587 closure[closureSize] = cp; 1588 closure[closureSize+1] = co; 1589 fifo[fifoSize] = cp; 1590 fifo[fifoSize+1] = co; 1591 } 1592 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 1593 while (fifoSize - fifoStart) { 1594 const PetscInt q = fifo[fifoStart]; 1595 const PetscInt o = fifo[fifoStart+1]; 1596 const PetscInt rev = o >= 0 ? 0 : 1; 1597 const PetscInt off = rev ? -(o+1) : o; 1598 1599 if (useCone) { 1600 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1601 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1602 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1603 } else { 1604 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1605 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1606 tmpO = NULL; 1607 } 1608 for (t = 0; t < tmpSize; ++t) { 1609 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1610 const PetscInt cp = tmp[i]; 1611 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 1612 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 1613 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 1614 PetscInt co = tmpO ? tmpO[i] : 0; 1615 PetscInt c; 1616 1617 if (rev) { 1618 PetscInt childSize, coff; 1619 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1620 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1621 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1622 } 1623 /* Check for duplicate */ 1624 for (c = 0; c < closureSize; c += 2) { 1625 if (closure[c] == cp) break; 1626 } 1627 if (c == closureSize) { 1628 closure[closureSize] = cp; 1629 closure[closureSize+1] = co; 1630 fifo[fifoSize] = cp; 1631 fifo[fifoSize+1] = co; 1632 closureSize += 2; 1633 fifoSize += 2; 1634 } 1635 } 1636 fifoStart += 2; 1637 } 1638 if (numPoints) *numPoints = closureSize/2; 1639 if (points) *points = closure; 1640 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1641 PetscFunctionReturn(0); 1642 } 1643 1644 #undef __FUNCT__ 1645 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1646 /*@C 1647 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1648 1649 Not collective 1650 1651 Input Parameters: 1652 + mesh - The DMPlex 1653 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1654 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1655 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 1656 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 1657 1658 Note: 1659 If not using internal storage (points is not NULL on input), this call is unnecessary 1660 1661 Fortran Notes: 1662 Since it returns an array, this routine is only available in Fortran 90, and you must 1663 include petsc.h90 in your code. 1664 1665 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1666 1667 Level: beginner 1668 1669 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1670 @*/ 1671 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1672 { 1673 PetscErrorCode ierr; 1674 1675 PetscFunctionBegin; 1676 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1677 if (numPoints) PetscValidIntPointer(numPoints,4); 1678 if (points) PetscValidPointer(points,5); 1679 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1680 if (numPoints) *numPoints = 0; 1681 PetscFunctionReturn(0); 1682 } 1683 1684 #undef __FUNCT__ 1685 #define __FUNCT__ "DMPlexGetMaxSizes" 1686 /*@ 1687 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1688 1689 Not collective 1690 1691 Input Parameter: 1692 . mesh - The DMPlex 1693 1694 Output Parameters: 1695 + maxConeSize - The maximum number of in-edges 1696 - maxSupportSize - The maximum number of out-edges 1697 1698 Level: beginner 1699 1700 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1701 @*/ 1702 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1703 { 1704 DM_Plex *mesh = (DM_Plex*) dm->data; 1705 1706 PetscFunctionBegin; 1707 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1708 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1709 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1710 PetscFunctionReturn(0); 1711 } 1712 1713 #undef __FUNCT__ 1714 #define __FUNCT__ "DMSetUp_Plex" 1715 PetscErrorCode DMSetUp_Plex(DM dm) 1716 { 1717 DM_Plex *mesh = (DM_Plex*) dm->data; 1718 PetscInt size; 1719 PetscErrorCode ierr; 1720 1721 PetscFunctionBegin; 1722 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1723 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1724 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1725 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 1726 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 1727 if (mesh->maxSupportSize) { 1728 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1729 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1730 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 1731 } 1732 PetscFunctionReturn(0); 1733 } 1734 1735 #undef __FUNCT__ 1736 #define __FUNCT__ "DMCreateSubDM_Plex" 1737 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1738 { 1739 PetscErrorCode ierr; 1740 1741 PetscFunctionBegin; 1742 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 1743 ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1744 PetscFunctionReturn(0); 1745 } 1746 1747 #undef __FUNCT__ 1748 #define __FUNCT__ "DMPlexSymmetrize" 1749 /*@ 1750 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1751 1752 Not collective 1753 1754 Input Parameter: 1755 . mesh - The DMPlex 1756 1757 Output Parameter: 1758 1759 Note: 1760 This should be called after all calls to DMPlexSetCone() 1761 1762 Level: beginner 1763 1764 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1765 @*/ 1766 PetscErrorCode DMPlexSymmetrize(DM dm) 1767 { 1768 DM_Plex *mesh = (DM_Plex*) dm->data; 1769 PetscInt *offsets; 1770 PetscInt supportSize; 1771 PetscInt pStart, pEnd, p; 1772 PetscErrorCode ierr; 1773 1774 PetscFunctionBegin; 1775 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1776 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1777 /* Calculate support sizes */ 1778 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1779 for (p = pStart; p < pEnd; ++p) { 1780 PetscInt dof, off, c; 1781 1782 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1783 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1784 for (c = off; c < off+dof; ++c) { 1785 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1786 } 1787 } 1788 for (p = pStart; p < pEnd; ++p) { 1789 PetscInt dof; 1790 1791 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1792 1793 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1794 } 1795 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1796 /* Calculate supports */ 1797 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1798 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 1799 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 1800 for (p = pStart; p < pEnd; ++p) { 1801 PetscInt dof, off, c; 1802 1803 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1804 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1805 for (c = off; c < off+dof; ++c) { 1806 const PetscInt q = mesh->cones[c]; 1807 PetscInt offS; 1808 1809 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1810 1811 mesh->supports[offS+offsets[q]] = p; 1812 ++offsets[q]; 1813 } 1814 } 1815 ierr = PetscFree(offsets);CHKERRQ(ierr); 1816 PetscFunctionReturn(0); 1817 } 1818 1819 #undef __FUNCT__ 1820 #define __FUNCT__ "DMPlexStratify" 1821 /*@ 1822 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 1823 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 1824 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 1825 the DAG. 1826 1827 Not collective 1828 1829 Input Parameter: 1830 . mesh - The DMPlex 1831 1832 Output Parameter: 1833 1834 Notes: 1835 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 1836 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 1837 1838 This should be called after all calls to DMPlexSymmetrize() 1839 1840 Level: beginner 1841 1842 .seealso: DMPlexCreate(), DMPlexSymmetrize() 1843 @*/ 1844 PetscErrorCode DMPlexStratify(DM dm) 1845 { 1846 DMLabel label; 1847 PetscInt pStart, pEnd, p; 1848 PetscInt numRoots = 0, numLeaves = 0; 1849 PetscErrorCode ierr; 1850 1851 PetscFunctionBegin; 1852 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1853 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1854 /* Calculate depth */ 1855 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1856 ierr = DMPlexCreateLabel(dm, "depth");CHKERRQ(ierr); 1857 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 1858 /* Initialize roots and count leaves */ 1859 for (p = pStart; p < pEnd; ++p) { 1860 PetscInt coneSize, supportSize; 1861 1862 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1863 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1864 if (!coneSize && supportSize) { 1865 ++numRoots; 1866 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 1867 } else if (!supportSize && coneSize) { 1868 ++numLeaves; 1869 } else if (!supportSize && !coneSize) { 1870 /* Isolated points */ 1871 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 1872 } 1873 } 1874 if (numRoots + numLeaves == (pEnd - pStart)) { 1875 for (p = pStart; p < pEnd; ++p) { 1876 PetscInt coneSize, supportSize; 1877 1878 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1879 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1880 if (!supportSize && coneSize) { 1881 ierr = DMLabelSetValue(label, p, 1);CHKERRQ(ierr); 1882 } 1883 } 1884 } else { 1885 IS pointIS; 1886 PetscInt numPoints = 0, level = 0; 1887 1888 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 1889 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 1890 while (numPoints) { 1891 const PetscInt *points; 1892 const PetscInt newLevel = level+1; 1893 1894 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 1895 for (p = 0; p < numPoints; ++p) { 1896 const PetscInt point = points[p]; 1897 const PetscInt *support; 1898 PetscInt supportSize, s; 1899 1900 ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr); 1901 ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 1902 for (s = 0; s < supportSize; ++s) { 1903 ierr = DMLabelSetValue(label, support[s], newLevel);CHKERRQ(ierr); 1904 } 1905 } 1906 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 1907 ++level; 1908 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1909 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 1910 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 1911 else {numPoints = 0;} 1912 } 1913 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1914 } 1915 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1916 PetscFunctionReturn(0); 1917 } 1918 1919 #undef __FUNCT__ 1920 #define __FUNCT__ "DMPlexGetJoin" 1921 /*@C 1922 DMPlexGetJoin - Get an array for the join of the set of points 1923 1924 Not Collective 1925 1926 Input Parameters: 1927 + dm - The DMPlex object 1928 . numPoints - The number of input points for the join 1929 - points - The input points 1930 1931 Output Parameters: 1932 + numCoveredPoints - The number of points in the join 1933 - coveredPoints - The points in the join 1934 1935 Level: intermediate 1936 1937 Note: Currently, this is restricted to a single level join 1938 1939 Fortran Notes: 1940 Since it returns an array, this routine is only available in Fortran 90, and you must 1941 include petsc.h90 in your code. 1942 1943 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1944 1945 .keywords: mesh 1946 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 1947 @*/ 1948 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 1949 { 1950 DM_Plex *mesh = (DM_Plex*) dm->data; 1951 PetscInt *join[2]; 1952 PetscInt joinSize, i = 0; 1953 PetscInt dof, off, p, c, m; 1954 PetscErrorCode ierr; 1955 1956 PetscFunctionBegin; 1957 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1958 PetscValidPointer(points, 2); 1959 PetscValidPointer(numCoveredPoints, 3); 1960 PetscValidPointer(coveredPoints, 4); 1961 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 1962 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 1963 /* Copy in support of first point */ 1964 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 1965 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 1966 for (joinSize = 0; joinSize < dof; ++joinSize) { 1967 join[i][joinSize] = mesh->supports[off+joinSize]; 1968 } 1969 /* Check each successive support */ 1970 for (p = 1; p < numPoints; ++p) { 1971 PetscInt newJoinSize = 0; 1972 1973 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 1974 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 1975 for (c = 0; c < dof; ++c) { 1976 const PetscInt point = mesh->supports[off+c]; 1977 1978 for (m = 0; m < joinSize; ++m) { 1979 if (point == join[i][m]) { 1980 join[1-i][newJoinSize++] = point; 1981 break; 1982 } 1983 } 1984 } 1985 joinSize = newJoinSize; 1986 i = 1-i; 1987 } 1988 *numCoveredPoints = joinSize; 1989 *coveredPoints = join[i]; 1990 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 1991 PetscFunctionReturn(0); 1992 } 1993 1994 #undef __FUNCT__ 1995 #define __FUNCT__ "DMPlexRestoreJoin" 1996 /*@C 1997 DMPlexRestoreJoin - Restore an array for the join of the set of points 1998 1999 Not Collective 2000 2001 Input Parameters: 2002 + dm - The DMPlex object 2003 . numPoints - The number of input points for the join 2004 - points - The input points 2005 2006 Output Parameters: 2007 + numCoveredPoints - The number of points in the join 2008 - coveredPoints - The points in the join 2009 2010 Fortran Notes: 2011 Since it returns an array, this routine is only available in Fortran 90, and you must 2012 include petsc.h90 in your code. 2013 2014 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2015 2016 Level: intermediate 2017 2018 .keywords: mesh 2019 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2020 @*/ 2021 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2022 { 2023 PetscErrorCode ierr; 2024 2025 PetscFunctionBegin; 2026 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2027 if (points) PetscValidIntPointer(points,3); 2028 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2029 PetscValidPointer(coveredPoints, 5); 2030 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2031 if (numCoveredPoints) *numCoveredPoints = 0; 2032 PetscFunctionReturn(0); 2033 } 2034 2035 #undef __FUNCT__ 2036 #define __FUNCT__ "DMPlexGetFullJoin" 2037 /*@C 2038 DMPlexGetFullJoin - Get an array for the join of the set of points 2039 2040 Not Collective 2041 2042 Input Parameters: 2043 + dm - The DMPlex object 2044 . numPoints - The number of input points for the join 2045 - points - The input points 2046 2047 Output Parameters: 2048 + numCoveredPoints - The number of points in the join 2049 - coveredPoints - The points in the join 2050 2051 Fortran Notes: 2052 Since it returns an array, this routine is only available in Fortran 90, and you must 2053 include petsc.h90 in your code. 2054 2055 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2056 2057 Level: intermediate 2058 2059 .keywords: mesh 2060 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2061 @*/ 2062 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2063 { 2064 DM_Plex *mesh = (DM_Plex*) dm->data; 2065 PetscInt *offsets, **closures; 2066 PetscInt *join[2]; 2067 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2068 PetscInt p, d, c, m; 2069 PetscErrorCode ierr; 2070 2071 PetscFunctionBegin; 2072 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2073 PetscValidPointer(points, 2); 2074 PetscValidPointer(numCoveredPoints, 3); 2075 PetscValidPointer(coveredPoints, 4); 2076 2077 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2078 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 2079 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2080 maxSize = PetscPowInt(mesh->maxSupportSize,depth+1); 2081 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2082 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2083 2084 for (p = 0; p < numPoints; ++p) { 2085 PetscInt closureSize; 2086 2087 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2088 2089 offsets[p*(depth+2)+0] = 0; 2090 for (d = 0; d < depth+1; ++d) { 2091 PetscInt pStart, pEnd, i; 2092 2093 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2094 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2095 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2096 offsets[p*(depth+2)+d+1] = i; 2097 break; 2098 } 2099 } 2100 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2101 } 2102 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); 2103 } 2104 for (d = 0; d < depth+1; ++d) { 2105 PetscInt dof; 2106 2107 /* Copy in support of first point */ 2108 dof = offsets[d+1] - offsets[d]; 2109 for (joinSize = 0; joinSize < dof; ++joinSize) { 2110 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2111 } 2112 /* Check each successive cone */ 2113 for (p = 1; p < numPoints && joinSize; ++p) { 2114 PetscInt newJoinSize = 0; 2115 2116 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2117 for (c = 0; c < dof; ++c) { 2118 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2119 2120 for (m = 0; m < joinSize; ++m) { 2121 if (point == join[i][m]) { 2122 join[1-i][newJoinSize++] = point; 2123 break; 2124 } 2125 } 2126 } 2127 joinSize = newJoinSize; 2128 i = 1-i; 2129 } 2130 if (joinSize) break; 2131 } 2132 *numCoveredPoints = joinSize; 2133 *coveredPoints = join[i]; 2134 for (p = 0; p < numPoints; ++p) { 2135 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2136 } 2137 ierr = PetscFree(closures);CHKERRQ(ierr); 2138 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2139 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2140 PetscFunctionReturn(0); 2141 } 2142 2143 #undef __FUNCT__ 2144 #define __FUNCT__ "DMPlexGetMeet" 2145 /*@C 2146 DMPlexGetMeet - Get an array for the meet of the set of points 2147 2148 Not Collective 2149 2150 Input Parameters: 2151 + dm - The DMPlex object 2152 . numPoints - The number of input points for the meet 2153 - points - The input points 2154 2155 Output Parameters: 2156 + numCoveredPoints - The number of points in the meet 2157 - coveredPoints - The points in the meet 2158 2159 Level: intermediate 2160 2161 Note: Currently, this is restricted to a single level meet 2162 2163 Fortran Notes: 2164 Since it returns an array, this routine is only available in Fortran 90, and you must 2165 include petsc.h90 in your code. 2166 2167 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2168 2169 .keywords: mesh 2170 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2171 @*/ 2172 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2173 { 2174 DM_Plex *mesh = (DM_Plex*) dm->data; 2175 PetscInt *meet[2]; 2176 PetscInt meetSize, i = 0; 2177 PetscInt dof, off, p, c, m; 2178 PetscErrorCode ierr; 2179 2180 PetscFunctionBegin; 2181 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2182 PetscValidPointer(points, 2); 2183 PetscValidPointer(numCoveringPoints, 3); 2184 PetscValidPointer(coveringPoints, 4); 2185 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2186 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2187 /* Copy in cone of first point */ 2188 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2189 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2190 for (meetSize = 0; meetSize < dof; ++meetSize) { 2191 meet[i][meetSize] = mesh->cones[off+meetSize]; 2192 } 2193 /* Check each successive cone */ 2194 for (p = 1; p < numPoints; ++p) { 2195 PetscInt newMeetSize = 0; 2196 2197 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2198 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2199 for (c = 0; c < dof; ++c) { 2200 const PetscInt point = mesh->cones[off+c]; 2201 2202 for (m = 0; m < meetSize; ++m) { 2203 if (point == meet[i][m]) { 2204 meet[1-i][newMeetSize++] = point; 2205 break; 2206 } 2207 } 2208 } 2209 meetSize = newMeetSize; 2210 i = 1-i; 2211 } 2212 *numCoveringPoints = meetSize; 2213 *coveringPoints = meet[i]; 2214 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2215 PetscFunctionReturn(0); 2216 } 2217 2218 #undef __FUNCT__ 2219 #define __FUNCT__ "DMPlexRestoreMeet" 2220 /*@C 2221 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2222 2223 Not Collective 2224 2225 Input Parameters: 2226 + dm - The DMPlex object 2227 . numPoints - The number of input points for the meet 2228 - points - The input points 2229 2230 Output Parameters: 2231 + numCoveredPoints - The number of points in the meet 2232 - coveredPoints - The points in the meet 2233 2234 Level: intermediate 2235 2236 Fortran Notes: 2237 Since it returns an array, this routine is only available in Fortran 90, and you must 2238 include petsc.h90 in your code. 2239 2240 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2241 2242 .keywords: mesh 2243 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2244 @*/ 2245 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2246 { 2247 PetscErrorCode ierr; 2248 2249 PetscFunctionBegin; 2250 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2251 if (points) PetscValidIntPointer(points,3); 2252 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2253 PetscValidPointer(coveredPoints,5); 2254 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2255 if (numCoveredPoints) *numCoveredPoints = 0; 2256 PetscFunctionReturn(0); 2257 } 2258 2259 #undef __FUNCT__ 2260 #define __FUNCT__ "DMPlexGetFullMeet" 2261 /*@C 2262 DMPlexGetFullMeet - Get an array for the meet of the set of points 2263 2264 Not Collective 2265 2266 Input Parameters: 2267 + dm - The DMPlex object 2268 . numPoints - The number of input points for the meet 2269 - points - The input points 2270 2271 Output Parameters: 2272 + numCoveredPoints - The number of points in the meet 2273 - coveredPoints - The points in the meet 2274 2275 Level: intermediate 2276 2277 Fortran Notes: 2278 Since it returns an array, this routine is only available in Fortran 90, and you must 2279 include petsc.h90 in your code. 2280 2281 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2282 2283 .keywords: mesh 2284 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2285 @*/ 2286 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2287 { 2288 DM_Plex *mesh = (DM_Plex*) dm->data; 2289 PetscInt *offsets, **closures; 2290 PetscInt *meet[2]; 2291 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2292 PetscInt p, h, c, m; 2293 PetscErrorCode ierr; 2294 2295 PetscFunctionBegin; 2296 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2297 PetscValidPointer(points, 2); 2298 PetscValidPointer(numCoveredPoints, 3); 2299 PetscValidPointer(coveredPoints, 4); 2300 2301 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2302 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 2303 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2304 maxSize = PetscPowInt(mesh->maxConeSize,height+1); 2305 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2306 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2307 2308 for (p = 0; p < numPoints; ++p) { 2309 PetscInt closureSize; 2310 2311 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2312 2313 offsets[p*(height+2)+0] = 0; 2314 for (h = 0; h < height+1; ++h) { 2315 PetscInt pStart, pEnd, i; 2316 2317 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2318 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2319 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2320 offsets[p*(height+2)+h+1] = i; 2321 break; 2322 } 2323 } 2324 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2325 } 2326 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); 2327 } 2328 for (h = 0; h < height+1; ++h) { 2329 PetscInt dof; 2330 2331 /* Copy in cone of first point */ 2332 dof = offsets[h+1] - offsets[h]; 2333 for (meetSize = 0; meetSize < dof; ++meetSize) { 2334 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2335 } 2336 /* Check each successive cone */ 2337 for (p = 1; p < numPoints && meetSize; ++p) { 2338 PetscInt newMeetSize = 0; 2339 2340 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2341 for (c = 0; c < dof; ++c) { 2342 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2343 2344 for (m = 0; m < meetSize; ++m) { 2345 if (point == meet[i][m]) { 2346 meet[1-i][newMeetSize++] = point; 2347 break; 2348 } 2349 } 2350 } 2351 meetSize = newMeetSize; 2352 i = 1-i; 2353 } 2354 if (meetSize) break; 2355 } 2356 *numCoveredPoints = meetSize; 2357 *coveredPoints = meet[i]; 2358 for (p = 0; p < numPoints; ++p) { 2359 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2360 } 2361 ierr = PetscFree(closures);CHKERRQ(ierr); 2362 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2363 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2364 PetscFunctionReturn(0); 2365 } 2366 2367 #undef __FUNCT__ 2368 #define __FUNCT__ "DMPlexEqual" 2369 /*@C 2370 DMPlexEqual - Determine if two DMs have the same topology 2371 2372 Not Collective 2373 2374 Input Parameters: 2375 + dmA - A DMPlex object 2376 - dmB - A DMPlex object 2377 2378 Output Parameters: 2379 . equal - PETSC_TRUE if the topologies are identical 2380 2381 Level: intermediate 2382 2383 Notes: 2384 We are not solving graph isomorphism, so we do not permutation. 2385 2386 .keywords: mesh 2387 .seealso: DMPlexGetCone() 2388 @*/ 2389 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 2390 { 2391 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 2392 PetscErrorCode ierr; 2393 2394 PetscFunctionBegin; 2395 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 2396 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 2397 PetscValidPointer(equal, 3); 2398 2399 *equal = PETSC_FALSE; 2400 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 2401 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 2402 if (depth != depthB) PetscFunctionReturn(0); 2403 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 2404 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 2405 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 2406 for (p = pStart; p < pEnd; ++p) { 2407 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 2408 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 2409 2410 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 2411 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 2412 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 2413 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 2414 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 2415 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 2416 if (coneSize != coneSizeB) PetscFunctionReturn(0); 2417 for (c = 0; c < coneSize; ++c) { 2418 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 2419 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 2420 } 2421 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 2422 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 2423 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 2424 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 2425 if (supportSize != supportSizeB) PetscFunctionReturn(0); 2426 for (s = 0; s < supportSize; ++s) { 2427 if (support[s] != supportB[s]) PetscFunctionReturn(0); 2428 } 2429 } 2430 *equal = PETSC_TRUE; 2431 PetscFunctionReturn(0); 2432 } 2433 2434 #undef __FUNCT__ 2435 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2436 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2437 { 2438 MPI_Comm comm; 2439 PetscErrorCode ierr; 2440 2441 PetscFunctionBegin; 2442 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2443 PetscValidPointer(numFaceVertices,3); 2444 switch (cellDim) { 2445 case 0: 2446 *numFaceVertices = 0; 2447 break; 2448 case 1: 2449 *numFaceVertices = 1; 2450 break; 2451 case 2: 2452 switch (numCorners) { 2453 case 3: /* triangle */ 2454 *numFaceVertices = 2; /* Edge has 2 vertices */ 2455 break; 2456 case 4: /* quadrilateral */ 2457 *numFaceVertices = 2; /* Edge has 2 vertices */ 2458 break; 2459 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2460 *numFaceVertices = 3; /* Edge has 3 vertices */ 2461 break; 2462 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2463 *numFaceVertices = 3; /* Edge has 3 vertices */ 2464 break; 2465 default: 2466 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2467 } 2468 break; 2469 case 3: 2470 switch (numCorners) { 2471 case 4: /* tetradehdron */ 2472 *numFaceVertices = 3; /* Face has 3 vertices */ 2473 break; 2474 case 6: /* tet cohesive cells */ 2475 *numFaceVertices = 4; /* Face has 4 vertices */ 2476 break; 2477 case 8: /* hexahedron */ 2478 *numFaceVertices = 4; /* Face has 4 vertices */ 2479 break; 2480 case 9: /* tet cohesive Lagrange cells */ 2481 *numFaceVertices = 6; /* Face has 6 vertices */ 2482 break; 2483 case 10: /* quadratic tetrahedron */ 2484 *numFaceVertices = 6; /* Face has 6 vertices */ 2485 break; 2486 case 12: /* hex cohesive Lagrange cells */ 2487 *numFaceVertices = 6; /* Face has 6 vertices */ 2488 break; 2489 case 18: /* quadratic tet cohesive Lagrange cells */ 2490 *numFaceVertices = 6; /* Face has 6 vertices */ 2491 break; 2492 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2493 *numFaceVertices = 9; /* Face has 9 vertices */ 2494 break; 2495 default: 2496 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2497 } 2498 break; 2499 default: 2500 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2501 } 2502 PetscFunctionReturn(0); 2503 } 2504 2505 #undef __FUNCT__ 2506 #define __FUNCT__ "DMPlexOrient" 2507 /* Trys to give the mesh a consistent orientation */ 2508 PetscErrorCode DMPlexOrient(DM dm) 2509 { 2510 PetscBT seenCells, flippedCells, seenFaces; 2511 PetscInt *faceFIFO, fTop, fBottom; 2512 PetscInt dim, h, cStart, cEnd, c, fStart, fEnd, face, maxConeSize, *revcone, *revconeO; 2513 PetscErrorCode ierr; 2514 2515 PetscFunctionBegin; 2516 /* Truth Table 2517 mismatch flips do action mismatch flipA ^ flipB action 2518 F 0 flips no F F F 2519 F 1 flip yes F T T 2520 F 2 flips no T F T 2521 T 0 flips yes T T F 2522 T 1 flip no 2523 T 2 flips yes 2524 */ 2525 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2526 ierr = DMPlexGetVTKCellHeight(dm, &h);CHKERRQ(ierr); 2527 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 2528 ierr = DMPlexGetHeightStratum(dm, h+1, &fStart, &fEnd);CHKERRQ(ierr); 2529 ierr = PetscBTCreate(cEnd - cStart, &seenCells);CHKERRQ(ierr); 2530 ierr = PetscBTMemzero(cEnd - cStart, seenCells);CHKERRQ(ierr); 2531 ierr = PetscBTCreate(cEnd - cStart, &flippedCells);CHKERRQ(ierr); 2532 ierr = PetscBTMemzero(cEnd - cStart, flippedCells);CHKERRQ(ierr); 2533 ierr = PetscBTCreate(fEnd - fStart, &seenFaces);CHKERRQ(ierr); 2534 ierr = PetscBTMemzero(fEnd - fStart, seenFaces);CHKERRQ(ierr); 2535 ierr = PetscMalloc1((fEnd - fStart), &faceFIFO);CHKERRQ(ierr); 2536 fTop = fBottom = 0; 2537 /* Initialize FIFO with first cell */ 2538 if (cEnd > cStart) { 2539 const PetscInt *cone; 2540 PetscInt coneSize; 2541 2542 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 2543 ierr = DMPlexGetCone(dm, cStart, &cone);CHKERRQ(ierr); 2544 for (c = 0; c < coneSize; ++c) { 2545 faceFIFO[fBottom++] = cone[c]; 2546 ierr = PetscBTSet(seenFaces, cone[c]-fStart);CHKERRQ(ierr); 2547 } 2548 } 2549 /* Consider each face in FIFO */ 2550 while (fTop < fBottom) { 2551 const PetscInt *support, *coneA, *coneB, *coneOA, *coneOB; 2552 PetscInt supportSize, coneSizeA, coneSizeB, posA = -1, posB = -1; 2553 PetscInt seenA, flippedA, seenB, flippedB, mismatch; 2554 2555 face = faceFIFO[fTop++]; 2556 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 2557 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 2558 if (supportSize < 2) continue; 2559 if (supportSize != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Faces should separate only two cells, not %d", supportSize); 2560 seenA = PetscBTLookup(seenCells, support[0]-cStart); 2561 flippedA = PetscBTLookup(flippedCells, support[0]-cStart) ? 1 : 0; 2562 seenB = PetscBTLookup(seenCells, support[1]-cStart); 2563 flippedB = PetscBTLookup(flippedCells, support[1]-cStart) ? 1 : 0; 2564 2565 ierr = DMPlexGetConeSize(dm, support[0], &coneSizeA);CHKERRQ(ierr); 2566 ierr = DMPlexGetConeSize(dm, support[1], &coneSizeB);CHKERRQ(ierr); 2567 ierr = DMPlexGetCone(dm, support[0], &coneA);CHKERRQ(ierr); 2568 ierr = DMPlexGetCone(dm, support[1], &coneB);CHKERRQ(ierr); 2569 ierr = DMPlexGetConeOrientation(dm, support[0], &coneOA);CHKERRQ(ierr); 2570 ierr = DMPlexGetConeOrientation(dm, support[1], &coneOB);CHKERRQ(ierr); 2571 for (c = 0; c < coneSizeA; ++c) { 2572 if (!PetscBTLookup(seenFaces, coneA[c]-fStart)) { 2573 faceFIFO[fBottom++] = coneA[c]; 2574 ierr = PetscBTSet(seenFaces, coneA[c]-fStart);CHKERRQ(ierr); 2575 } 2576 if (coneA[c] == face) posA = c; 2577 if (fBottom > fEnd-fStart) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face %d was pushed exceeding capacity %d > %d", coneA[c], fBottom, fEnd-fStart); 2578 } 2579 if (posA < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d could not be located in cell %d", face, support[0]); 2580 for (c = 0; c < coneSizeB; ++c) { 2581 if (!PetscBTLookup(seenFaces, coneB[c]-fStart)) { 2582 faceFIFO[fBottom++] = coneB[c]; 2583 ierr = PetscBTSet(seenFaces, coneB[c]-fStart);CHKERRQ(ierr); 2584 } 2585 if (coneB[c] == face) posB = c; 2586 if (fBottom > fEnd-fStart) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face %d was pushed exceeding capacity %d > %d", coneA[c], fBottom, fEnd-fStart); 2587 } 2588 if (posB < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d could not be located in cell %d", face, support[1]); 2589 2590 if (dim == 1) { 2591 mismatch = posA == posB; 2592 } else { 2593 mismatch = coneOA[posA] == coneOB[posB]; 2594 } 2595 2596 if (mismatch ^ (flippedA ^ flippedB)) { 2597 if (seenA && seenB) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Previously seen cells %d and %d do not match: Fault mesh is non-orientable", support[0], support[1]); 2598 if (!seenA && !flippedA) { 2599 ierr = PetscBTSet(flippedCells, support[0]-cStart);CHKERRQ(ierr); 2600 } else if (!seenB && !flippedB) { 2601 ierr = PetscBTSet(flippedCells, support[1]-cStart);CHKERRQ(ierr); 2602 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent mesh orientation: Fault mesh is non-orientable"); 2603 } else if (mismatch && flippedA && flippedB) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Attempt to flip already flipped cell: Fault mesh is non-orientable"); 2604 ierr = PetscBTSet(seenCells, support[0]-cStart);CHKERRQ(ierr); 2605 ierr = PetscBTSet(seenCells, support[1]-cStart);CHKERRQ(ierr); 2606 } 2607 /* Now all subdomains are oriented, but we need a consistent parallel orientation */ 2608 { 2609 /* Find a representative face (edge) separating pairs of procs */ 2610 PetscSF sf; 2611 const PetscInt *lpoints; 2612 const PetscSFNode *rpoints; 2613 PetscInt *neighbors, *nranks; 2614 PetscInt numLeaves, numRoots, numNeighbors = 0, l, n; 2615 2616 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 2617 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &lpoints, &rpoints);CHKERRQ(ierr); 2618 if (numLeaves >= 0) { 2619 const PetscInt *cone, *ornt, *support; 2620 PetscInt coneSize, supportSize; 2621 int *rornt, *lornt; /* PetscSF cannot handle smaller than int */ 2622 PetscBool *match, flipped = PETSC_FALSE; 2623 2624 ierr = PetscMalloc1(numLeaves,&neighbors);CHKERRQ(ierr); 2625 /* I know this is p^2 time in general, but for bounded degree its alright */ 2626 for (l = 0; l < numLeaves; ++l) { 2627 const PetscInt face = lpoints[l]; 2628 if ((face >= fStart) && (face < fEnd)) { 2629 const PetscInt rank = rpoints[l].rank; 2630 for (n = 0; n < numNeighbors; ++n) if (rank == rpoints[neighbors[n]].rank) break; 2631 if (n >= numNeighbors) { 2632 PetscInt supportSize; 2633 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 2634 if (supportSize != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Boundary faces should see one cell, not %d", supportSize); 2635 neighbors[numNeighbors++] = l; 2636 } 2637 } 2638 } 2639 ierr = PetscCalloc4(numNeighbors,&match,numNeighbors,&nranks,numRoots,&rornt,numRoots,&lornt);CHKERRQ(ierr); 2640 for (face = fStart; face < fEnd; ++face) { 2641 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 2642 if (supportSize != 1) continue; 2643 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 2644 2645 ierr = DMPlexGetCone(dm, support[0], &cone);CHKERRQ(ierr); 2646 ierr = DMPlexGetConeSize(dm, support[0], &coneSize);CHKERRQ(ierr); 2647 ierr = DMPlexGetConeOrientation(dm, support[0], &ornt);CHKERRQ(ierr); 2648 for (c = 0; c < coneSize; ++c) if (cone[c] == face) break; 2649 if (dim == 1) { 2650 /* Use cone position instead, shifted to -1 or 1 */ 2651 rornt[face] = c*2-1; 2652 } else { 2653 if (PetscBTLookup(flippedCells, support[0]-cStart)) rornt[face] = ornt[c] < 0 ? -1 : 1; 2654 else rornt[face] = ornt[c] < 0 ? 1 : -1; 2655 } 2656 } 2657 /* Mark each edge with match or nomatch */ 2658 ierr = PetscSFBcastBegin(sf, MPI_INT, rornt, lornt);CHKERRQ(ierr); 2659 ierr = PetscSFBcastEnd(sf, MPI_INT, rornt, lornt);CHKERRQ(ierr); 2660 for (n = 0; n < numNeighbors; ++n) { 2661 const PetscInt face = lpoints[neighbors[n]]; 2662 2663 if (rornt[face]*lornt[face] < 0) match[n] = PETSC_TRUE; 2664 else match[n] = PETSC_FALSE; 2665 nranks[n] = rpoints[neighbors[n]].rank; 2666 } 2667 /* Collect the graph on 0 */ 2668 { 2669 MPI_Comm comm = PetscObjectComm((PetscObject) sf); 2670 PetscBT seenProcs, flippedProcs; 2671 PetscInt *procFIFO, pTop, pBottom; 2672 PetscInt *adj = NULL; 2673 PetscBool *val = NULL; 2674 PetscMPIInt *recvcounts = NULL, *displs = NULL, p; 2675 PetscMPIInt N = numNeighbors, numProcs = 0, rank; 2676 PetscInt debug = 0; 2677 2678 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2679 if (!rank) {ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr);} 2680 ierr = PetscCalloc2(numProcs,&recvcounts,numProcs+1,&displs);CHKERRQ(ierr); 2681 ierr = MPI_Gather(&N, 1, MPI_INT, recvcounts, 1, MPI_INT, 0, comm);CHKERRQ(ierr); 2682 for (p = 0; p < numProcs; ++p) { 2683 displs[p+1] = displs[p] + recvcounts[p]; 2684 } 2685 if (!rank) {ierr = PetscMalloc2(displs[numProcs],&adj,displs[numProcs],&val);CHKERRQ(ierr);} 2686 ierr = MPI_Gatherv(nranks, numNeighbors, MPIU_INT, adj, recvcounts, displs, MPIU_INT, 0, comm);CHKERRQ(ierr); 2687 ierr = MPI_Gatherv(match, numNeighbors, MPIU_BOOL, val, recvcounts, displs, MPIU_BOOL, 0, comm);CHKERRQ(ierr); 2688 if (debug) { 2689 for (p = 0; p < numProcs; ++p) { 2690 ierr = PetscPrintf(comm, "Proc %d:\n", p); 2691 for (n = 0; n < recvcounts[p]; ++n) { 2692 ierr = PetscPrintf(comm, " edge %d (%d):\n", adj[displs[p]+n], val[displs[p]+n]); 2693 } 2694 } 2695 } 2696 ierr = PetscBTCreate(numProcs, &seenProcs);CHKERRQ(ierr); 2697 ierr = PetscBTMemzero(numProcs, seenProcs);CHKERRQ(ierr); 2698 ierr = PetscBTCreate(numProcs, &flippedProcs);CHKERRQ(ierr); 2699 ierr = PetscBTMemzero(numProcs, flippedProcs);CHKERRQ(ierr); 2700 ierr = PetscMalloc1(numProcs,&procFIFO);CHKERRQ(ierr); 2701 pTop = pBottom = 0; 2702 for (p = 0; p < numProcs; ++p) { 2703 if (PetscBTLookup(seenProcs, p)) continue; 2704 /* Initialize FIFO with next proc */ 2705 procFIFO[pBottom++] = p; 2706 ierr = PetscBTSet(seenProcs, p);CHKERRQ(ierr); 2707 /* Consider each proc in FIFO */ 2708 while (pTop < pBottom) { 2709 PetscInt proc, nproc, seen, flippedA, flippedB, mismatch; 2710 2711 proc = procFIFO[pTop++]; 2712 flippedA = PetscBTLookup(flippedProcs, proc) ? 1 : 0; 2713 /* Loop over neighboring procs */ 2714 for (n = 0; n < recvcounts[proc]; ++n) { 2715 nproc = adj[displs[proc]+n]; 2716 mismatch = val[displs[proc]+n] ? 0 : 1; 2717 seen = PetscBTLookup(seenProcs, nproc); 2718 flippedB = PetscBTLookup(flippedProcs, nproc) ? 1 : 0; 2719 2720 if (mismatch ^ (flippedA ^ flippedB)) { 2721 if (seen) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Previously seen procs %d and %d do not match: Fault mesh is non-orientable", proc, nproc); 2722 if (!flippedB) { 2723 ierr = PetscBTSet(flippedProcs, nproc);CHKERRQ(ierr); 2724 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent mesh orientation: Fault mesh is non-orientable"); 2725 } else if (mismatch && flippedA && flippedB) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Attempt to flip already flipped cell: Fault mesh is non-orientable"); 2726 if (!seen) { 2727 procFIFO[pBottom++] = nproc; 2728 ierr = PetscBTSet(seenProcs, nproc);CHKERRQ(ierr); 2729 } 2730 } 2731 } 2732 } 2733 ierr = PetscFree(procFIFO);CHKERRQ(ierr); 2734 2735 ierr = PetscFree2(recvcounts,displs);CHKERRQ(ierr); 2736 ierr = PetscFree2(adj,val);CHKERRQ(ierr); 2737 { 2738 PetscBool *flips; 2739 2740 ierr = PetscMalloc1(numProcs,&flips);CHKERRQ(ierr); 2741 for (p = 0; p < numProcs; ++p) { 2742 flips[p] = PetscBTLookup(flippedProcs, p) ? PETSC_TRUE : PETSC_FALSE; 2743 if (debug && flips[p]) {ierr = PetscPrintf(comm, "Flipping Proc %d:\n", p);} 2744 } 2745 ierr = MPI_Scatter(flips, 1, MPIU_BOOL, &flipped, 1, MPIU_BOOL, 0, comm);CHKERRQ(ierr); 2746 ierr = PetscFree(flips);CHKERRQ(ierr); 2747 } 2748 ierr = PetscBTDestroy(&seenProcs);CHKERRQ(ierr); 2749 ierr = PetscBTDestroy(&flippedProcs);CHKERRQ(ierr); 2750 } 2751 ierr = PetscFree4(match,nranks,rornt,lornt);CHKERRQ(ierr); 2752 ierr = PetscFree(neighbors);CHKERRQ(ierr); 2753 if (flipped) {for (c = cStart; c < cEnd; ++c) {ierr = PetscBTNegate(flippedCells, c-cStart);CHKERRQ(ierr);}} 2754 } 2755 } 2756 /* Reverse flipped cells in the mesh */ 2757 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, NULL);CHKERRQ(ierr); 2758 ierr = DMGetWorkArray(dm, maxConeSize, PETSC_INT, &revcone);CHKERRQ(ierr); 2759 ierr = DMGetWorkArray(dm, maxConeSize, PETSC_INT, &revconeO);CHKERRQ(ierr); 2760 for (c = cStart; c < cEnd; ++c) { 2761 const PetscInt *cone, *coneO, *support; 2762 PetscInt coneSize, supportSize, faceSize, cp, sp; 2763 2764 if (!PetscBTLookup(flippedCells, c-cStart)) continue; 2765 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 2766 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 2767 ierr = DMPlexGetConeOrientation(dm, c, &coneO);CHKERRQ(ierr); 2768 for (cp = 0; cp < coneSize; ++cp) { 2769 const PetscInt rcp = coneSize-cp-1; 2770 2771 ierr = DMPlexGetConeSize(dm, cone[rcp], &faceSize);CHKERRQ(ierr); 2772 revcone[cp] = cone[rcp]; 2773 revconeO[cp] = coneO[rcp] >= 0 ? -(faceSize-coneO[rcp]) : faceSize+coneO[rcp]; 2774 } 2775 ierr = DMPlexSetCone(dm, c, revcone);CHKERRQ(ierr); 2776 ierr = DMPlexSetConeOrientation(dm, c, revconeO);CHKERRQ(ierr); 2777 /* Reverse orientations of support */ 2778 faceSize = coneSize; 2779 ierr = DMPlexGetSupportSize(dm, c, &supportSize);CHKERRQ(ierr); 2780 ierr = DMPlexGetSupport(dm, c, &support);CHKERRQ(ierr); 2781 for (sp = 0; sp < supportSize; ++sp) { 2782 ierr = DMPlexGetConeSize(dm, support[sp], &coneSize);CHKERRQ(ierr); 2783 ierr = DMPlexGetCone(dm, support[sp], &cone);CHKERRQ(ierr); 2784 ierr = DMPlexGetConeOrientation(dm, support[sp], &coneO);CHKERRQ(ierr); 2785 for (cp = 0; cp < coneSize; ++cp) { 2786 if (cone[cp] != c) continue; 2787 ierr = DMPlexInsertConeOrientation(dm, support[sp], cp, coneO[cp] >= 0 ? -(faceSize-coneO[cp]) : faceSize+coneO[cp]);CHKERRQ(ierr); 2788 } 2789 } 2790 } 2791 ierr = DMRestoreWorkArray(dm, maxConeSize, PETSC_INT, &revcone);CHKERRQ(ierr); 2792 ierr = DMRestoreWorkArray(dm, maxConeSize, PETSC_INT, &revconeO);CHKERRQ(ierr); 2793 ierr = PetscBTDestroy(&seenCells);CHKERRQ(ierr); 2794 ierr = PetscBTDestroy(&flippedCells);CHKERRQ(ierr); 2795 ierr = PetscBTDestroy(&seenFaces);CHKERRQ(ierr); 2796 ierr = PetscFree(faceFIFO);CHKERRQ(ierr); 2797 PetscFunctionReturn(0); 2798 } 2799 2800 #undef __FUNCT__ 2801 #define __FUNCT__ "DMPlexInvertCell" 2802 /*@C 2803 DMPlexInvertCell - This flips tetrahedron and hexahedron orientation since Plex stores them internally with outward normals. Other cells are left untouched. 2804 2805 Input Parameters: 2806 + numCorners - The number of vertices in a cell 2807 - cone - The incoming cone 2808 2809 Output Parameter: 2810 . cone - The inverted cone (in-place) 2811 2812 Level: developer 2813 2814 .seealso: DMPlexGenerate() 2815 @*/ 2816 PetscErrorCode DMPlexInvertCell(PetscInt dim, PetscInt numCorners, int cone[]) 2817 { 2818 int tmpc; 2819 2820 PetscFunctionBegin; 2821 if (dim != 3) PetscFunctionReturn(0); 2822 switch (numCorners) { 2823 case 4: 2824 tmpc = cone[0]; 2825 cone[0] = cone[1]; 2826 cone[1] = tmpc; 2827 break; 2828 case 8: 2829 tmpc = cone[1]; 2830 cone[1] = cone[3]; 2831 cone[3] = tmpc; 2832 break; 2833 default: break; 2834 } 2835 PetscFunctionReturn(0); 2836 } 2837 2838 #undef __FUNCT__ 2839 #define __FUNCT__ "DMPlexInvertCells_Internal" 2840 /* This is to fix the tetrahedron orientation from TetGen */ 2841 PETSC_UNUSED static PetscErrorCode DMPlexInvertCells_Internal(PetscInt dim, PetscInt numCells, PetscInt numCorners, int cells[]) 2842 { 2843 PetscInt bound = numCells*numCorners, coff; 2844 PetscErrorCode ierr; 2845 2846 PetscFunctionBegin; 2847 for (coff = 0; coff < bound; coff += numCorners) { 2848 ierr = DMPlexInvertCell(dim, numCorners, &cells[coff]);CHKERRQ(ierr); 2849 } 2850 PetscFunctionReturn(0); 2851 } 2852 2853 #if defined(PETSC_HAVE_TRIANGLE) 2854 #include <triangle.h> 2855 2856 #undef __FUNCT__ 2857 #define __FUNCT__ "InitInput_Triangle" 2858 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 2859 { 2860 PetscFunctionBegin; 2861 inputCtx->numberofpoints = 0; 2862 inputCtx->numberofpointattributes = 0; 2863 inputCtx->pointlist = NULL; 2864 inputCtx->pointattributelist = NULL; 2865 inputCtx->pointmarkerlist = NULL; 2866 inputCtx->numberofsegments = 0; 2867 inputCtx->segmentlist = NULL; 2868 inputCtx->segmentmarkerlist = NULL; 2869 inputCtx->numberoftriangleattributes = 0; 2870 inputCtx->trianglelist = NULL; 2871 inputCtx->numberofholes = 0; 2872 inputCtx->holelist = NULL; 2873 inputCtx->numberofregions = 0; 2874 inputCtx->regionlist = NULL; 2875 PetscFunctionReturn(0); 2876 } 2877 2878 #undef __FUNCT__ 2879 #define __FUNCT__ "InitOutput_Triangle" 2880 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 2881 { 2882 PetscFunctionBegin; 2883 outputCtx->numberofpoints = 0; 2884 outputCtx->pointlist = NULL; 2885 outputCtx->pointattributelist = NULL; 2886 outputCtx->pointmarkerlist = NULL; 2887 outputCtx->numberoftriangles = 0; 2888 outputCtx->trianglelist = NULL; 2889 outputCtx->triangleattributelist = NULL; 2890 outputCtx->neighborlist = NULL; 2891 outputCtx->segmentlist = NULL; 2892 outputCtx->segmentmarkerlist = NULL; 2893 outputCtx->numberofedges = 0; 2894 outputCtx->edgelist = NULL; 2895 outputCtx->edgemarkerlist = NULL; 2896 PetscFunctionReturn(0); 2897 } 2898 2899 #undef __FUNCT__ 2900 #define __FUNCT__ "FiniOutput_Triangle" 2901 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 2902 { 2903 PetscFunctionBegin; 2904 free(outputCtx->pointlist); 2905 free(outputCtx->pointmarkerlist); 2906 free(outputCtx->segmentlist); 2907 free(outputCtx->segmentmarkerlist); 2908 free(outputCtx->edgelist); 2909 free(outputCtx->edgemarkerlist); 2910 free(outputCtx->trianglelist); 2911 free(outputCtx->neighborlist); 2912 PetscFunctionReturn(0); 2913 } 2914 2915 #undef __FUNCT__ 2916 #define __FUNCT__ "DMPlexGenerate_Triangle" 2917 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 2918 { 2919 MPI_Comm comm; 2920 PetscInt dim = 2; 2921 const PetscBool createConvexHull = PETSC_FALSE; 2922 const PetscBool constrained = PETSC_FALSE; 2923 struct triangulateio in; 2924 struct triangulateio out; 2925 PetscInt vStart, vEnd, v, eStart, eEnd, e; 2926 PetscMPIInt rank; 2927 PetscErrorCode ierr; 2928 2929 PetscFunctionBegin; 2930 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 2931 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2932 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 2933 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 2934 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 2935 2936 in.numberofpoints = vEnd - vStart; 2937 if (in.numberofpoints > 0) { 2938 PetscSection coordSection; 2939 Vec coordinates; 2940 PetscScalar *array; 2941 2942 ierr = PetscMalloc1(in.numberofpoints*dim, &in.pointlist);CHKERRQ(ierr); 2943 ierr = PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);CHKERRQ(ierr); 2944 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 2945 ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 2946 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 2947 for (v = vStart; v < vEnd; ++v) { 2948 const PetscInt idx = v - vStart; 2949 PetscInt off, d; 2950 2951 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 2952 for (d = 0; d < dim; ++d) { 2953 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 2954 } 2955 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 2956 } 2957 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 2958 } 2959 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 2960 in.numberofsegments = eEnd - eStart; 2961 if (in.numberofsegments > 0) { 2962 ierr = PetscMalloc1(in.numberofsegments*2, &in.segmentlist);CHKERRQ(ierr); 2963 ierr = PetscMalloc1(in.numberofsegments, &in.segmentmarkerlist);CHKERRQ(ierr); 2964 for (e = eStart; e < eEnd; ++e) { 2965 const PetscInt idx = e - eStart; 2966 const PetscInt *cone; 2967 2968 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 2969 2970 in.segmentlist[idx*2+0] = cone[0] - vStart; 2971 in.segmentlist[idx*2+1] = cone[1] - vStart; 2972 2973 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 2974 } 2975 } 2976 #if 0 /* Do not currently support holes */ 2977 PetscReal *holeCoords; 2978 PetscInt h, d; 2979 2980 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 2981 if (in.numberofholes > 0) { 2982 ierr = PetscMalloc1(in.numberofholes*dim, &in.holelist);CHKERRQ(ierr); 2983 for (h = 0; h < in.numberofholes; ++h) { 2984 for (d = 0; d < dim; ++d) { 2985 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 2986 } 2987 } 2988 } 2989 #endif 2990 if (!rank) { 2991 char args[32]; 2992 2993 /* Take away 'Q' for verbose output */ 2994 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 2995 if (createConvexHull) { 2996 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 2997 } 2998 if (constrained) { 2999 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 3000 } 3001 triangulate(args, &in, &out, NULL); 3002 } 3003 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 3004 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 3005 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 3006 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 3007 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 3008 3009 { 3010 const PetscInt numCorners = 3; 3011 const PetscInt numCells = out.numberoftriangles; 3012 const PetscInt numVertices = out.numberofpoints; 3013 const int *cells = out.trianglelist; 3014 const double *meshCoords = out.pointlist; 3015 3016 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3017 /* Set labels */ 3018 for (v = 0; v < numVertices; ++v) { 3019 if (out.pointmarkerlist[v]) { 3020 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3021 } 3022 } 3023 if (interpolate) { 3024 for (e = 0; e < out.numberofedges; e++) { 3025 if (out.edgemarkerlist[e]) { 3026 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3027 const PetscInt *edges; 3028 PetscInt numEdges; 3029 3030 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3031 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3032 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3033 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3034 } 3035 } 3036 } 3037 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3038 } 3039 #if 0 /* Do not currently support holes */ 3040 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 3041 #endif 3042 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 3043 PetscFunctionReturn(0); 3044 } 3045 3046 #undef __FUNCT__ 3047 #define __FUNCT__ "DMPlexRefine_Triangle" 3048 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 3049 { 3050 MPI_Comm comm; 3051 PetscInt dim = 2; 3052 struct triangulateio in; 3053 struct triangulateio out; 3054 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3055 PetscMPIInt rank; 3056 PetscErrorCode ierr; 3057 3058 PetscFunctionBegin; 3059 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3060 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3061 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 3062 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 3063 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3064 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3065 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3066 3067 in.numberofpoints = vEnd - vStart; 3068 if (in.numberofpoints > 0) { 3069 PetscSection coordSection; 3070 Vec coordinates; 3071 PetscScalar *array; 3072 3073 ierr = PetscMalloc1(in.numberofpoints*dim, &in.pointlist);CHKERRQ(ierr); 3074 ierr = PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);CHKERRQ(ierr); 3075 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3076 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3077 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3078 for (v = vStart; v < vEnd; ++v) { 3079 const PetscInt idx = v - vStart; 3080 PetscInt off, d; 3081 3082 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3083 for (d = 0; d < dim; ++d) { 3084 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3085 } 3086 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3087 } 3088 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3089 } 3090 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3091 3092 in.numberofcorners = 3; 3093 in.numberoftriangles = cEnd - cStart; 3094 3095 in.trianglearealist = (double*) maxVolumes; 3096 if (in.numberoftriangles > 0) { 3097 ierr = PetscMalloc1(in.numberoftriangles*in.numberofcorners, &in.trianglelist);CHKERRQ(ierr); 3098 for (c = cStart; c < cEnd; ++c) { 3099 const PetscInt idx = c - cStart; 3100 PetscInt *closure = NULL; 3101 PetscInt closureSize; 3102 3103 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3104 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 3105 for (v = 0; v < 3; ++v) { 3106 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 3107 } 3108 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3109 } 3110 } 3111 /* TODO: Segment markers are missing on input */ 3112 #if 0 /* Do not currently support holes */ 3113 PetscReal *holeCoords; 3114 PetscInt h, d; 3115 3116 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 3117 if (in.numberofholes > 0) { 3118 ierr = PetscMalloc1(in.numberofholes*dim, &in.holelist);CHKERRQ(ierr); 3119 for (h = 0; h < in.numberofholes; ++h) { 3120 for (d = 0; d < dim; ++d) { 3121 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 3122 } 3123 } 3124 } 3125 #endif 3126 if (!rank) { 3127 char args[32]; 3128 3129 /* Take away 'Q' for verbose output */ 3130 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 3131 triangulate(args, &in, &out, NULL); 3132 } 3133 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 3134 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 3135 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 3136 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 3137 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 3138 3139 { 3140 const PetscInt numCorners = 3; 3141 const PetscInt numCells = out.numberoftriangles; 3142 const PetscInt numVertices = out.numberofpoints; 3143 const int *cells = out.trianglelist; 3144 const double *meshCoords = out.pointlist; 3145 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3146 3147 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3148 /* Set labels */ 3149 for (v = 0; v < numVertices; ++v) { 3150 if (out.pointmarkerlist[v]) { 3151 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3152 } 3153 } 3154 if (interpolate) { 3155 PetscInt e; 3156 3157 for (e = 0; e < out.numberofedges; e++) { 3158 if (out.edgemarkerlist[e]) { 3159 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3160 const PetscInt *edges; 3161 PetscInt numEdges; 3162 3163 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3164 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3165 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3166 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3167 } 3168 } 3169 } 3170 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3171 } 3172 #if 0 /* Do not currently support holes */ 3173 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 3174 #endif 3175 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 3176 PetscFunctionReturn(0); 3177 } 3178 #endif 3179 3180 #if defined(PETSC_HAVE_TETGEN) 3181 #include <tetgen.h> 3182 #undef __FUNCT__ 3183 #define __FUNCT__ "DMPlexGenerate_Tetgen" 3184 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 3185 { 3186 MPI_Comm comm; 3187 const PetscInt dim = 3; 3188 ::tetgenio in; 3189 ::tetgenio out; 3190 PetscInt vStart, vEnd, v, fStart, fEnd, f; 3191 PetscMPIInt rank; 3192 PetscErrorCode ierr; 3193 3194 PetscFunctionBegin; 3195 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3196 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3197 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3198 in.numberofpoints = vEnd - vStart; 3199 if (in.numberofpoints > 0) { 3200 PetscSection coordSection; 3201 Vec coordinates; 3202 PetscScalar *array; 3203 3204 in.pointlist = new double[in.numberofpoints*dim]; 3205 in.pointmarkerlist = new int[in.numberofpoints]; 3206 3207 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3208 ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3209 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3210 for (v = vStart; v < vEnd; ++v) { 3211 const PetscInt idx = v - vStart; 3212 PetscInt off, d; 3213 3214 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3215 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 3216 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3217 } 3218 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3219 } 3220 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 3221 3222 in.numberoffacets = fEnd - fStart; 3223 if (in.numberoffacets > 0) { 3224 in.facetlist = new tetgenio::facet[in.numberoffacets]; 3225 in.facetmarkerlist = new int[in.numberoffacets]; 3226 for (f = fStart; f < fEnd; ++f) { 3227 const PetscInt idx = f - fStart; 3228 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 3229 3230 in.facetlist[idx].numberofpolygons = 1; 3231 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 3232 in.facetlist[idx].numberofholes = 0; 3233 in.facetlist[idx].holelist = NULL; 3234 3235 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3236 for (p = 0; p < numPoints*2; p += 2) { 3237 const PetscInt point = points[p]; 3238 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 3239 } 3240 3241 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 3242 poly->numberofvertices = numVertices; 3243 poly->vertexlist = new int[poly->numberofvertices]; 3244 for (v = 0; v < numVertices; ++v) { 3245 const PetscInt vIdx = points[v] - vStart; 3246 poly->vertexlist[v] = vIdx; 3247 } 3248 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 3249 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3250 } 3251 } 3252 if (!rank) { 3253 char args[32]; 3254 3255 /* Take away 'Q' for verbose output */ 3256 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 3257 ::tetrahedralize(args, &in, &out); 3258 } 3259 { 3260 const PetscInt numCorners = 4; 3261 const PetscInt numCells = out.numberoftetrahedra; 3262 const PetscInt numVertices = out.numberofpoints; 3263 const double *meshCoords = out.pointlist; 3264 int *cells = out.tetrahedronlist; 3265 3266 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3267 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3268 /* Set labels */ 3269 for (v = 0; v < numVertices; ++v) { 3270 if (out.pointmarkerlist[v]) { 3271 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3272 } 3273 } 3274 if (interpolate) { 3275 PetscInt e; 3276 3277 for (e = 0; e < out.numberofedges; e++) { 3278 if (out.edgemarkerlist[e]) { 3279 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3280 const PetscInt *edges; 3281 PetscInt numEdges; 3282 3283 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3284 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3285 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3286 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3287 } 3288 } 3289 for (f = 0; f < out.numberoftrifaces; f++) { 3290 if (out.trifacemarkerlist[f]) { 3291 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 3292 const PetscInt *faces; 3293 PetscInt numFaces; 3294 3295 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3296 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3297 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 3298 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3299 } 3300 } 3301 } 3302 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3303 } 3304 PetscFunctionReturn(0); 3305 } 3306 3307 #undef __FUNCT__ 3308 #define __FUNCT__ "DMPlexRefine_Tetgen" 3309 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 3310 { 3311 MPI_Comm comm; 3312 const PetscInt dim = 3; 3313 ::tetgenio in; 3314 ::tetgenio out; 3315 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3316 PetscMPIInt rank; 3317 PetscErrorCode ierr; 3318 3319 PetscFunctionBegin; 3320 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3321 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3322 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3323 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3324 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3325 3326 in.numberofpoints = vEnd - vStart; 3327 if (in.numberofpoints > 0) { 3328 PetscSection coordSection; 3329 Vec coordinates; 3330 PetscScalar *array; 3331 3332 in.pointlist = new double[in.numberofpoints*dim]; 3333 in.pointmarkerlist = new int[in.numberofpoints]; 3334 3335 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3336 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3337 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3338 for (v = vStart; v < vEnd; ++v) { 3339 const PetscInt idx = v - vStart; 3340 PetscInt off, d; 3341 3342 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3343 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 3344 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 3345 } 3346 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3347 } 3348 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3349 3350 in.numberofcorners = 4; 3351 in.numberoftetrahedra = cEnd - cStart; 3352 in.tetrahedronvolumelist = (double*) maxVolumes; 3353 if (in.numberoftetrahedra > 0) { 3354 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 3355 for (c = cStart; c < cEnd; ++c) { 3356 const PetscInt idx = c - cStart; 3357 PetscInt *closure = NULL; 3358 PetscInt closureSize; 3359 3360 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3361 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 3362 for (v = 0; v < 4; ++v) { 3363 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 3364 } 3365 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3366 } 3367 } 3368 /* TODO: Put in boundary faces with markers */ 3369 if (!rank) { 3370 char args[32]; 3371 3372 /* Take away 'Q' for verbose output */ 3373 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 3374 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 3375 ::tetrahedralize(args, &in, &out); 3376 } 3377 in.tetrahedronvolumelist = NULL; 3378 3379 { 3380 const PetscInt numCorners = 4; 3381 const PetscInt numCells = out.numberoftetrahedra; 3382 const PetscInt numVertices = out.numberofpoints; 3383 const double *meshCoords = out.pointlist; 3384 int *cells = out.tetrahedronlist; 3385 3386 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3387 3388 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3389 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3390 /* Set labels */ 3391 for (v = 0; v < numVertices; ++v) { 3392 if (out.pointmarkerlist[v]) { 3393 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 3394 } 3395 } 3396 if (interpolate) { 3397 PetscInt e, f; 3398 3399 for (e = 0; e < out.numberofedges; e++) { 3400 if (out.edgemarkerlist[e]) { 3401 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 3402 const PetscInt *edges; 3403 PetscInt numEdges; 3404 3405 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3406 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3407 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 3408 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3409 } 3410 } 3411 for (f = 0; f < out.numberoftrifaces; f++) { 3412 if (out.trifacemarkerlist[f]) { 3413 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 3414 const PetscInt *faces; 3415 PetscInt numFaces; 3416 3417 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3418 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3419 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 3420 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3421 } 3422 } 3423 } 3424 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3425 } 3426 PetscFunctionReturn(0); 3427 } 3428 #endif 3429 3430 #if defined(PETSC_HAVE_CTETGEN) 3431 #include <ctetgen.h> 3432 3433 #undef __FUNCT__ 3434 #define __FUNCT__ "DMPlexGenerate_CTetgen" 3435 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 3436 { 3437 MPI_Comm comm; 3438 const PetscInt dim = 3; 3439 PLC *in, *out; 3440 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 3441 PetscMPIInt rank; 3442 PetscErrorCode ierr; 3443 3444 PetscFunctionBegin; 3445 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 3446 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3447 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3448 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 3449 ierr = PLCCreate(&in);CHKERRQ(ierr); 3450 ierr = PLCCreate(&out);CHKERRQ(ierr); 3451 3452 in->numberofpoints = vEnd - vStart; 3453 if (in->numberofpoints > 0) { 3454 PetscSection coordSection; 3455 Vec coordinates; 3456 PetscScalar *array; 3457 3458 ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr); 3459 ierr = PetscMalloc1(in->numberofpoints, &in->pointmarkerlist);CHKERRQ(ierr); 3460 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 3461 ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 3462 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3463 for (v = vStart; v < vEnd; ++v) { 3464 const PetscInt idx = v - vStart; 3465 PetscInt off, d, m; 3466 3467 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3468 for (d = 0; d < dim; ++d) { 3469 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3470 } 3471 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 3472 3473 in->pointmarkerlist[idx] = (int) m; 3474 } 3475 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3476 } 3477 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 3478 3479 in->numberoffacets = fEnd - fStart; 3480 if (in->numberoffacets > 0) { 3481 ierr = PetscMalloc1(in->numberoffacets, &in->facetlist);CHKERRQ(ierr); 3482 ierr = PetscMalloc1(in->numberoffacets, &in->facetmarkerlist);CHKERRQ(ierr); 3483 for (f = fStart; f < fEnd; ++f) { 3484 const PetscInt idx = f - fStart; 3485 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 3486 polygon *poly; 3487 3488 in->facetlist[idx].numberofpolygons = 1; 3489 3490 ierr = PetscMalloc1(in->facetlist[idx].numberofpolygons, &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 3491 3492 in->facetlist[idx].numberofholes = 0; 3493 in->facetlist[idx].holelist = NULL; 3494 3495 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3496 for (p = 0; p < numPoints*2; p += 2) { 3497 const PetscInt point = points[p]; 3498 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 3499 } 3500 3501 poly = in->facetlist[idx].polygonlist; 3502 poly->numberofvertices = numVertices; 3503 ierr = PetscMalloc1(poly->numberofvertices, &poly->vertexlist);CHKERRQ(ierr); 3504 for (v = 0; v < numVertices; ++v) { 3505 const PetscInt vIdx = points[v] - vStart; 3506 poly->vertexlist[v] = vIdx; 3507 } 3508 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 3509 in->facetmarkerlist[idx] = (int) m; 3510 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3511 } 3512 } 3513 if (!rank) { 3514 TetGenOpts t; 3515 3516 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3517 t.in = boundary; /* Should go away */ 3518 t.plc = 1; 3519 t.quality = 1; 3520 t.edgesout = 1; 3521 t.zeroindex = 1; 3522 t.quiet = 1; 3523 t.verbose = verbose; 3524 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3525 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3526 } 3527 { 3528 const PetscInt numCorners = 4; 3529 const PetscInt numCells = out->numberoftetrahedra; 3530 const PetscInt numVertices = out->numberofpoints; 3531 const double *meshCoords = out->pointlist; 3532 int *cells = out->tetrahedronlist; 3533 3534 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3535 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 3536 /* Set labels */ 3537 for (v = 0; v < numVertices; ++v) { 3538 if (out->pointmarkerlist[v]) { 3539 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 3540 } 3541 } 3542 if (interpolate) { 3543 PetscInt e; 3544 3545 for (e = 0; e < out->numberofedges; e++) { 3546 if (out->edgemarkerlist[e]) { 3547 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 3548 const PetscInt *edges; 3549 PetscInt numEdges; 3550 3551 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3552 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3553 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 3554 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3555 } 3556 } 3557 for (f = 0; f < out->numberoftrifaces; f++) { 3558 if (out->trifacemarkerlist[f]) { 3559 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 3560 const PetscInt *faces; 3561 PetscInt numFaces; 3562 3563 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3564 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3565 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 3566 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3567 } 3568 } 3569 } 3570 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 3571 } 3572 3573 ierr = PLCDestroy(&in);CHKERRQ(ierr); 3574 ierr = PLCDestroy(&out);CHKERRQ(ierr); 3575 PetscFunctionReturn(0); 3576 } 3577 3578 #undef __FUNCT__ 3579 #define __FUNCT__ "DMPlexRefine_CTetgen" 3580 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 3581 { 3582 MPI_Comm comm; 3583 const PetscInt dim = 3; 3584 PLC *in, *out; 3585 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 3586 PetscMPIInt rank; 3587 PetscErrorCode ierr; 3588 3589 PetscFunctionBegin; 3590 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3591 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 3592 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3593 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3594 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 3595 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3596 ierr = PLCCreate(&in);CHKERRQ(ierr); 3597 ierr = PLCCreate(&out);CHKERRQ(ierr); 3598 3599 in->numberofpoints = vEnd - vStart; 3600 if (in->numberofpoints > 0) { 3601 PetscSection coordSection; 3602 Vec coordinates; 3603 PetscScalar *array; 3604 3605 ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr); 3606 ierr = PetscMalloc1(in->numberofpoints, &in->pointmarkerlist);CHKERRQ(ierr); 3607 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3608 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3609 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 3610 for (v = vStart; v < vEnd; ++v) { 3611 const PetscInt idx = v - vStart; 3612 PetscInt off, d, m; 3613 3614 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3615 for (d = 0; d < dim; ++d) { 3616 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 3617 } 3618 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 3619 3620 in->pointmarkerlist[idx] = (int) m; 3621 } 3622 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 3623 } 3624 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3625 3626 in->numberofcorners = 4; 3627 in->numberoftetrahedra = cEnd - cStart; 3628 in->tetrahedronvolumelist = maxVolumes; 3629 if (in->numberoftetrahedra > 0) { 3630 ierr = PetscMalloc1(in->numberoftetrahedra*in->numberofcorners, &in->tetrahedronlist);CHKERRQ(ierr); 3631 for (c = cStart; c < cEnd; ++c) { 3632 const PetscInt idx = c - cStart; 3633 PetscInt *closure = NULL; 3634 PetscInt closureSize; 3635 3636 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3637 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 3638 for (v = 0; v < 4; ++v) { 3639 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 3640 } 3641 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3642 } 3643 } 3644 if (!rank) { 3645 TetGenOpts t; 3646 3647 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 3648 3649 t.in = dm; /* Should go away */ 3650 t.refine = 1; 3651 t.varvolume = 1; 3652 t.quality = 1; 3653 t.edgesout = 1; 3654 t.zeroindex = 1; 3655 t.quiet = 1; 3656 t.verbose = verbose; /* Change this */ 3657 3658 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 3659 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 3660 } 3661 { 3662 const PetscInt numCorners = 4; 3663 const PetscInt numCells = out->numberoftetrahedra; 3664 const PetscInt numVertices = out->numberofpoints; 3665 const double *meshCoords = out->pointlist; 3666 int *cells = out->tetrahedronlist; 3667 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 3668 3669 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 3670 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 3671 /* Set labels */ 3672 for (v = 0; v < numVertices; ++v) { 3673 if (out->pointmarkerlist[v]) { 3674 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 3675 } 3676 } 3677 if (interpolate) { 3678 PetscInt e, f; 3679 3680 for (e = 0; e < out->numberofedges; e++) { 3681 if (out->edgemarkerlist[e]) { 3682 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 3683 const PetscInt *edges; 3684 PetscInt numEdges; 3685 3686 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3687 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 3688 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 3689 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 3690 } 3691 } 3692 for (f = 0; f < out->numberoftrifaces; f++) { 3693 if (out->trifacemarkerlist[f]) { 3694 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 3695 const PetscInt *faces; 3696 PetscInt numFaces; 3697 3698 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3699 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 3700 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 3701 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 3702 } 3703 } 3704 } 3705 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 3706 } 3707 ierr = PLCDestroy(&in);CHKERRQ(ierr); 3708 ierr = PLCDestroy(&out);CHKERRQ(ierr); 3709 PetscFunctionReturn(0); 3710 } 3711 #endif 3712 3713 #undef __FUNCT__ 3714 #define __FUNCT__ "DMPlexGenerate" 3715 /*@C 3716 DMPlexGenerate - Generates a mesh. 3717 3718 Not Collective 3719 3720 Input Parameters: 3721 + boundary - The DMPlex boundary object 3722 . name - The mesh generation package name 3723 - interpolate - Flag to create intermediate mesh elements 3724 3725 Output Parameter: 3726 . mesh - The DMPlex object 3727 3728 Level: intermediate 3729 3730 .keywords: mesh, elements 3731 .seealso: DMPlexCreate(), DMRefine() 3732 @*/ 3733 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 3734 { 3735 PetscInt dim; 3736 char genname[1024]; 3737 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 3738 PetscErrorCode ierr; 3739 3740 PetscFunctionBegin; 3741 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 3742 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 3743 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 3744 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 3745 if (flg) name = genname; 3746 if (name) { 3747 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 3748 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 3749 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 3750 } 3751 switch (dim) { 3752 case 1: 3753 if (!name || isTriangle) { 3754 #if defined(PETSC_HAVE_TRIANGLE) 3755 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 3756 #else 3757 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 3758 #endif 3759 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 3760 break; 3761 case 2: 3762 if (!name || isCTetgen) { 3763 #if defined(PETSC_HAVE_CTETGEN) 3764 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 3765 #else 3766 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 3767 #endif 3768 } else if (isTetgen) { 3769 #if defined(PETSC_HAVE_TETGEN) 3770 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 3771 #else 3772 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 3773 #endif 3774 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 3775 break; 3776 default: 3777 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 3778 } 3779 PetscFunctionReturn(0); 3780 } 3781 3782 #undef __FUNCT__ 3783 #define __FUNCT__ "DMRefine_Plex" 3784 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 3785 { 3786 PetscReal refinementLimit; 3787 PetscInt dim, cStart, cEnd; 3788 char genname[1024], *name = NULL; 3789 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 3790 PetscErrorCode ierr; 3791 3792 PetscFunctionBegin; 3793 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 3794 if (isUniform) { 3795 CellRefiner cellRefiner; 3796 3797 ierr = DMPlexGetCellRefiner_Internal(dm, &cellRefiner);CHKERRQ(ierr); 3798 ierr = DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 3799 PetscFunctionReturn(0); 3800 } 3801 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 3802 if (refinementLimit == 0.0) PetscFunctionReturn(0); 3803 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3804 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3805 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 3806 if (flg) name = genname; 3807 if (name) { 3808 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 3809 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 3810 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 3811 } 3812 switch (dim) { 3813 case 2: 3814 if (!name || isTriangle) { 3815 #if defined(PETSC_HAVE_TRIANGLE) 3816 double *maxVolumes; 3817 PetscInt c; 3818 3819 ierr = PetscMalloc1((cEnd - cStart), &maxVolumes);CHKERRQ(ierr); 3820 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 3821 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 3822 ierr = PetscFree(maxVolumes);CHKERRQ(ierr); 3823 #else 3824 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 3825 #endif 3826 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 3827 break; 3828 case 3: 3829 if (!name || isCTetgen) { 3830 #if defined(PETSC_HAVE_CTETGEN) 3831 PetscReal *maxVolumes; 3832 PetscInt c; 3833 3834 ierr = PetscMalloc1((cEnd - cStart), &maxVolumes);CHKERRQ(ierr); 3835 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 3836 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 3837 #else 3838 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 3839 #endif 3840 } else if (isTetgen) { 3841 #if defined(PETSC_HAVE_TETGEN) 3842 double *maxVolumes; 3843 PetscInt c; 3844 3845 ierr = PetscMalloc1((cEnd - cStart), &maxVolumes);CHKERRQ(ierr); 3846 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 3847 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 3848 #else 3849 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 3850 #endif 3851 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 3852 break; 3853 default: 3854 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 3855 } 3856 PetscFunctionReturn(0); 3857 } 3858 3859 #undef __FUNCT__ 3860 #define __FUNCT__ "DMRefineHierarchy_Plex" 3861 PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[]) 3862 { 3863 DM cdm = dm; 3864 PetscInt r; 3865 PetscBool isUniform; 3866 PetscErrorCode ierr; 3867 3868 PetscFunctionBegin; 3869 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 3870 if (!isUniform) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Non-uniform refinement is incompatible with the hierarchy"); 3871 for (r = 0; r < nlevels; ++r) { 3872 CellRefiner cellRefiner; 3873 3874 ierr = DMPlexGetCellRefiner_Internal(cdm, &cellRefiner);CHKERRQ(ierr); 3875 ierr = DMPlexRefineUniform_Internal(cdm, cellRefiner, &dmRefined[r]);CHKERRQ(ierr); 3876 ierr = DMPlexSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr); 3877 cdm = dmRefined[r]; 3878 } 3879 PetscFunctionReturn(0); 3880 } 3881 3882 #undef __FUNCT__ 3883 #define __FUNCT__ "DMCoarsen_Plex" 3884 PetscErrorCode DMCoarsen_Plex(DM dm, MPI_Comm comm, DM *dmCoarsened) 3885 { 3886 DM_Plex *mesh = (DM_Plex*) dm->data; 3887 PetscErrorCode ierr; 3888 3889 PetscFunctionBegin; 3890 ierr = PetscObjectReference((PetscObject) mesh->coarseMesh);CHKERRQ(ierr); 3891 *dmCoarsened = mesh->coarseMesh; 3892 PetscFunctionReturn(0); 3893 } 3894 3895 #undef __FUNCT__ 3896 #define __FUNCT__ "DMPlexGetDepthLabel" 3897 /*@ 3898 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 3899 3900 Not Collective 3901 3902 Input Parameter: 3903 . dm - The DMPlex object 3904 3905 Output Parameter: 3906 . depthLabel - The DMLabel recording point depth 3907 3908 Level: developer 3909 3910 .keywords: mesh, points 3911 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 3912 @*/ 3913 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 3914 { 3915 DM_Plex *mesh = (DM_Plex*) dm->data; 3916 PetscErrorCode ierr; 3917 3918 PetscFunctionBegin; 3919 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3920 PetscValidPointer(depthLabel, 2); 3921 if (!mesh->depthLabel) {ierr = DMPlexGetLabel(dm, "depth", &mesh->depthLabel);CHKERRQ(ierr);} 3922 *depthLabel = mesh->depthLabel; 3923 PetscFunctionReturn(0); 3924 } 3925 3926 #undef __FUNCT__ 3927 #define __FUNCT__ "DMPlexGetDepth" 3928 /*@ 3929 DMPlexGetDepth - Get the depth of the DAG representing this mesh 3930 3931 Not Collective 3932 3933 Input Parameter: 3934 . dm - The DMPlex object 3935 3936 Output Parameter: 3937 . depth - The number of strata (breadth first levels) in the DAG 3938 3939 Level: developer 3940 3941 .keywords: mesh, points 3942 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 3943 @*/ 3944 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 3945 { 3946 DMLabel label; 3947 PetscInt d = 0; 3948 PetscErrorCode ierr; 3949 3950 PetscFunctionBegin; 3951 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3952 PetscValidPointer(depth, 2); 3953 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3954 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 3955 *depth = d-1; 3956 PetscFunctionReturn(0); 3957 } 3958 3959 #undef __FUNCT__ 3960 #define __FUNCT__ "DMPlexGetDepthStratum" 3961 /*@ 3962 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 3963 3964 Not Collective 3965 3966 Input Parameters: 3967 + dm - The DMPlex object 3968 - stratumValue - The requested depth 3969 3970 Output Parameters: 3971 + start - The first point at this depth 3972 - end - One beyond the last point at this depth 3973 3974 Level: developer 3975 3976 .keywords: mesh, points 3977 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 3978 @*/ 3979 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 3980 { 3981 DMLabel label; 3982 PetscInt pStart, pEnd; 3983 PetscErrorCode ierr; 3984 3985 PetscFunctionBegin; 3986 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3987 if (start) {PetscValidPointer(start, 3); *start = 0;} 3988 if (end) {PetscValidPointer(end, 4); *end = 0;} 3989 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3990 if (pStart == pEnd) PetscFunctionReturn(0); 3991 if (stratumValue < 0) { 3992 if (start) *start = pStart; 3993 if (end) *end = pEnd; 3994 PetscFunctionReturn(0); 3995 } 3996 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3997 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 3998 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 3999 PetscFunctionReturn(0); 4000 } 4001 4002 #undef __FUNCT__ 4003 #define __FUNCT__ "DMPlexGetHeightStratum" 4004 /*@ 4005 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4006 4007 Not Collective 4008 4009 Input Parameters: 4010 + dm - The DMPlex object 4011 - stratumValue - The requested height 4012 4013 Output Parameters: 4014 + start - The first point at this height 4015 - end - One beyond the last point at this height 4016 4017 Level: developer 4018 4019 .keywords: mesh, points 4020 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 4021 @*/ 4022 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4023 { 4024 DMLabel label; 4025 PetscInt depth, pStart, pEnd; 4026 PetscErrorCode ierr; 4027 4028 PetscFunctionBegin; 4029 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4030 if (start) {PetscValidPointer(start, 3); *start = 0;} 4031 if (end) {PetscValidPointer(end, 4); *end = 0;} 4032 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4033 if (pStart == pEnd) PetscFunctionReturn(0); 4034 if (stratumValue < 0) { 4035 if (start) *start = pStart; 4036 if (end) *end = pEnd; 4037 PetscFunctionReturn(0); 4038 } 4039 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4040 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 4041 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4042 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4043 PetscFunctionReturn(0); 4044 } 4045 4046 #undef __FUNCT__ 4047 #define __FUNCT__ "DMPlexCreateSectionInitial" 4048 /* Set the number of dof on each point and separate by fields */ 4049 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 4050 { 4051 PetscInt *numDofTot; 4052 PetscInt depth, pStart = 0, pEnd = 0; 4053 PetscInt p, d, dep, f; 4054 PetscErrorCode ierr; 4055 4056 PetscFunctionBegin; 4057 ierr = PetscMalloc1((dim+1), &numDofTot);CHKERRQ(ierr); 4058 for (d = 0; d <= dim; ++d) { 4059 numDofTot[d] = 0; 4060 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 4061 } 4062 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 4063 if (numFields > 0) { 4064 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 4065 if (numComp) { 4066 for (f = 0; f < numFields; ++f) { 4067 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 4068 } 4069 } 4070 } 4071 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4072 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 4073 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4074 for (dep = 0; dep <= depth; ++dep) { 4075 d = dim == depth ? dep : (!dep ? 0 : dim); 4076 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 4077 for (p = pStart; p < pEnd; ++p) { 4078 for (f = 0; f < numFields; ++f) { 4079 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 4080 } 4081 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 4082 } 4083 } 4084 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 4085 PetscFunctionReturn(0); 4086 } 4087 4088 #undef __FUNCT__ 4089 #define __FUNCT__ "DMPlexCreateSectionBCDof" 4090 /* Set the number of dof on each point and separate by fields 4091 If constDof is PETSC_DETERMINE, constrain every dof on the point 4092 */ 4093 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 4094 { 4095 PetscInt numFields; 4096 PetscInt bc; 4097 PetscErrorCode ierr; 4098 4099 PetscFunctionBegin; 4100 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4101 for (bc = 0; bc < numBC; ++bc) { 4102 PetscInt field = 0; 4103 const PetscInt *idx; 4104 PetscInt n, i; 4105 4106 if (numFields) field = bcField[bc]; 4107 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 4108 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 4109 for (i = 0; i < n; ++i) { 4110 const PetscInt p = idx[i]; 4111 PetscInt numConst = constDof; 4112 4113 /* Constrain every dof on the point */ 4114 if (numConst < 0) { 4115 if (numFields) { 4116 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 4117 } else { 4118 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 4119 } 4120 } 4121 if (numFields) { 4122 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 4123 } 4124 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 4125 } 4126 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 4127 } 4128 PetscFunctionReturn(0); 4129 } 4130 4131 #undef __FUNCT__ 4132 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 4133 /* Set the constrained indices on each point and separate by fields */ 4134 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 4135 { 4136 PetscInt *maxConstraints; 4137 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 4138 PetscErrorCode ierr; 4139 4140 PetscFunctionBegin; 4141 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4142 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4143 ierr = PetscMalloc1((numFields+1), &maxConstraints);CHKERRQ(ierr); 4144 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 4145 for (p = pStart; p < pEnd; ++p) { 4146 PetscInt cdof; 4147 4148 if (numFields) { 4149 for (f = 0; f < numFields; ++f) { 4150 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 4151 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 4152 } 4153 } else { 4154 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 4155 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 4156 } 4157 } 4158 for (f = 0; f < numFields; ++f) { 4159 maxConstraints[numFields] += maxConstraints[f]; 4160 } 4161 if (maxConstraints[numFields]) { 4162 PetscInt *indices; 4163 4164 ierr = PetscMalloc1(maxConstraints[numFields], &indices);CHKERRQ(ierr); 4165 for (p = pStart; p < pEnd; ++p) { 4166 PetscInt cdof, d; 4167 4168 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 4169 if (cdof) { 4170 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 4171 if (numFields) { 4172 PetscInt numConst = 0, foff = 0; 4173 4174 for (f = 0; f < numFields; ++f) { 4175 PetscInt cfdof, fdof; 4176 4177 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 4178 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 4179 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 4180 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 4181 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 4182 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 4183 numConst += cfdof; 4184 foff += fdof; 4185 } 4186 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 4187 } else { 4188 for (d = 0; d < cdof; ++d) indices[d] = d; 4189 } 4190 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 4191 } 4192 } 4193 ierr = PetscFree(indices);CHKERRQ(ierr); 4194 } 4195 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 4196 PetscFunctionReturn(0); 4197 } 4198 4199 #undef __FUNCT__ 4200 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 4201 /* Set the constrained field indices on each point */ 4202 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 4203 { 4204 const PetscInt *points, *indices; 4205 PetscInt numFields, maxDof, numPoints, p, numConstraints; 4206 PetscErrorCode ierr; 4207 4208 PetscFunctionBegin; 4209 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4210 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 4211 4212 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 4213 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 4214 if (!constraintIndices) { 4215 PetscInt *idx, i; 4216 4217 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4218 ierr = PetscMalloc1(maxDof, &idx);CHKERRQ(ierr); 4219 for (i = 0; i < maxDof; ++i) idx[i] = i; 4220 for (p = 0; p < numPoints; ++p) { 4221 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 4222 } 4223 ierr = PetscFree(idx);CHKERRQ(ierr); 4224 } else { 4225 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 4226 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 4227 for (p = 0; p < numPoints; ++p) { 4228 PetscInt fcdof; 4229 4230 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 4231 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); 4232 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 4233 } 4234 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 4235 } 4236 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 4237 PetscFunctionReturn(0); 4238 } 4239 4240 #undef __FUNCT__ 4241 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 4242 /* Set the constrained indices on each point and separate by fields */ 4243 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 4244 { 4245 PetscInt *indices; 4246 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 4247 PetscErrorCode ierr; 4248 4249 PetscFunctionBegin; 4250 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4251 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 4252 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4253 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 4254 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4255 for (p = pStart; p < pEnd; ++p) { 4256 PetscInt cdof, d; 4257 4258 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 4259 if (cdof) { 4260 PetscInt numConst = 0, foff = 0; 4261 4262 for (f = 0; f < numFields; ++f) { 4263 const PetscInt *fcind; 4264 PetscInt fdof, fcdof; 4265 4266 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 4267 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 4268 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 4269 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 4270 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 4271 foff += fdof; 4272 numConst += fcdof; 4273 } 4274 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 4275 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 4276 } 4277 } 4278 ierr = PetscFree(indices);CHKERRQ(ierr); 4279 PetscFunctionReturn(0); 4280 } 4281 4282 #undef __FUNCT__ 4283 #define __FUNCT__ "DMPlexCreateSection" 4284 /*@C 4285 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 4286 4287 Not Collective 4288 4289 Input Parameters: 4290 + dm - The DMPlex object 4291 . dim - The spatial dimension of the problem 4292 . numFields - The number of fields in the problem 4293 . numComp - An array of size numFields that holds the number of components for each field 4294 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 4295 . numBC - The number of boundary conditions 4296 . bcField - An array of size numBC giving the field number for each boundry condition 4297 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 4298 4299 Output Parameter: 4300 . section - The PetscSection object 4301 4302 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 4303 nubmer of dof for field 0 on each edge. 4304 4305 Level: developer 4306 4307 Fortran Notes: 4308 A Fortran 90 version is available as DMPlexCreateSectionF90() 4309 4310 .keywords: mesh, elements 4311 .seealso: DMPlexCreate(), PetscSectionCreate() 4312 @*/ 4313 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 4314 { 4315 PetscErrorCode ierr; 4316 4317 PetscFunctionBegin; 4318 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 4319 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 4320 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 4321 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 4322 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 4323 PetscFunctionReturn(0); 4324 } 4325 4326 #undef __FUNCT__ 4327 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 4328 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4329 { 4330 PetscSection section; 4331 PetscErrorCode ierr; 4332 4333 PetscFunctionBegin; 4334 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4335 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4336 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 4337 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4338 PetscFunctionReturn(0); 4339 } 4340 4341 #undef __FUNCT__ 4342 #define __FUNCT__ "DMPlexGetConeSection" 4343 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 4344 { 4345 DM_Plex *mesh = (DM_Plex*) dm->data; 4346 4347 PetscFunctionBegin; 4348 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4349 if (section) *section = mesh->coneSection; 4350 PetscFunctionReturn(0); 4351 } 4352 4353 #undef __FUNCT__ 4354 #define __FUNCT__ "DMPlexGetSupportSection" 4355 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 4356 { 4357 DM_Plex *mesh = (DM_Plex*) dm->data; 4358 4359 PetscFunctionBegin; 4360 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4361 if (section) *section = mesh->supportSection; 4362 PetscFunctionReturn(0); 4363 } 4364 4365 #undef __FUNCT__ 4366 #define __FUNCT__ "DMPlexGetCones" 4367 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 4368 { 4369 DM_Plex *mesh = (DM_Plex*) dm->data; 4370 4371 PetscFunctionBegin; 4372 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4373 if (cones) *cones = mesh->cones; 4374 PetscFunctionReturn(0); 4375 } 4376 4377 #undef __FUNCT__ 4378 #define __FUNCT__ "DMPlexGetConeOrientations" 4379 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 4380 { 4381 DM_Plex *mesh = (DM_Plex*) dm->data; 4382 4383 PetscFunctionBegin; 4384 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4385 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 4386 PetscFunctionReturn(0); 4387 } 4388 4389 /******************************** FEM Support **********************************/ 4390 4391 #undef __FUNCT__ 4392 #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static" 4393 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4394 { 4395 PetscScalar *array, *vArray; 4396 const PetscInt *cone, *coneO; 4397 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 4398 PetscErrorCode ierr; 4399 4400 PetscFunctionBeginHot; 4401 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4402 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4403 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4404 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4405 if (!values || !*values) { 4406 if ((point >= pStart) && (point < pEnd)) { 4407 PetscInt dof; 4408 4409 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4410 size += dof; 4411 } 4412 for (p = 0; p < numPoints; ++p) { 4413 const PetscInt cp = cone[p]; 4414 PetscInt dof; 4415 4416 if ((cp < pStart) || (cp >= pEnd)) continue; 4417 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4418 size += dof; 4419 } 4420 if (!values) { 4421 if (csize) *csize = size; 4422 PetscFunctionReturn(0); 4423 } 4424 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 4425 } else { 4426 array = *values; 4427 } 4428 size = 0; 4429 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 4430 if ((point >= pStart) && (point < pEnd)) { 4431 PetscInt dof, off, d; 4432 PetscScalar *varr; 4433 4434 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4435 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4436 varr = &vArray[off]; 4437 for (d = 0; d < dof; ++d, ++offset) { 4438 array[offset] = varr[d]; 4439 } 4440 size += dof; 4441 } 4442 for (p = 0; p < numPoints; ++p) { 4443 const PetscInt cp = cone[p]; 4444 PetscInt o = coneO[p]; 4445 PetscInt dof, off, d; 4446 PetscScalar *varr; 4447 4448 if ((cp < pStart) || (cp >= pEnd)) continue; 4449 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4450 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 4451 varr = &vArray[off]; 4452 if (o >= 0) { 4453 for (d = 0; d < dof; ++d, ++offset) { 4454 array[offset] = varr[d]; 4455 } 4456 } else { 4457 for (d = dof-1; d >= 0; --d, ++offset) { 4458 array[offset] = varr[d]; 4459 } 4460 } 4461 size += dof; 4462 } 4463 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 4464 if (!*values) { 4465 if (csize) *csize = size; 4466 *values = array; 4467 } else { 4468 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 4469 *csize = size; 4470 } 4471 PetscFunctionReturn(0); 4472 } 4473 4474 #undef __FUNCT__ 4475 #define __FUNCT__ "DMPlexVecGetClosure_Static" 4476 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 4477 { 4478 PetscInt offset = 0, p; 4479 PetscErrorCode ierr; 4480 4481 PetscFunctionBeginHot; 4482 *size = 0; 4483 for (p = 0; p < numPoints*2; p += 2) { 4484 const PetscInt point = points[p]; 4485 const PetscInt o = points[p+1]; 4486 PetscInt dof, off, d; 4487 const PetscScalar *varr; 4488 4489 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4490 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4491 varr = &vArray[off]; 4492 if (o >= 0) { 4493 for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 4494 } else { 4495 for (d = dof-1; d >= 0; --d, ++offset) array[offset] = varr[d]; 4496 } 4497 } 4498 *size = offset; 4499 PetscFunctionReturn(0); 4500 } 4501 4502 #undef __FUNCT__ 4503 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 4504 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 4505 { 4506 PetscInt offset = 0, f; 4507 PetscErrorCode ierr; 4508 4509 PetscFunctionBeginHot; 4510 *size = 0; 4511 for (f = 0; f < numFields; ++f) { 4512 PetscInt fcomp, p; 4513 4514 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4515 for (p = 0; p < numPoints*2; p += 2) { 4516 const PetscInt point = points[p]; 4517 const PetscInt o = points[p+1]; 4518 PetscInt fdof, foff, d, c; 4519 const PetscScalar *varr; 4520 4521 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4522 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4523 varr = &vArray[foff]; 4524 if (o >= 0) { 4525 for (d = 0; d < fdof; ++d, ++offset) array[offset] = varr[d]; 4526 } else { 4527 for (d = fdof/fcomp-1; d >= 0; --d) { 4528 for (c = 0; c < fcomp; ++c, ++offset) { 4529 array[offset] = varr[d*fcomp+c]; 4530 } 4531 } 4532 } 4533 } 4534 } 4535 *size = offset; 4536 PetscFunctionReturn(0); 4537 } 4538 4539 #undef __FUNCT__ 4540 #define __FUNCT__ "DMPlexVecGetClosure" 4541 /*@C 4542 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 4543 4544 Not collective 4545 4546 Input Parameters: 4547 + dm - The DM 4548 . section - The section describing the layout in v, or NULL to use the default section 4549 . v - The local vector 4550 - point - The sieve point in the DM 4551 4552 Output Parameters: 4553 + csize - The number of values in the closure, or NULL 4554 - values - The array of values, which is a borrowed array and should not be freed 4555 4556 Fortran Notes: 4557 Since it returns an array, this routine is only available in Fortran 90, and you must 4558 include petsc.h90 in your code. 4559 4560 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4561 4562 Level: intermediate 4563 4564 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4565 @*/ 4566 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4567 { 4568 PetscSection clSection; 4569 IS clPoints; 4570 PetscScalar *array, *vArray; 4571 PetscInt *points = NULL; 4572 const PetscInt *clp; 4573 PetscInt depth, numFields, numPoints, size; 4574 PetscErrorCode ierr; 4575 4576 PetscFunctionBeginHot; 4577 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4578 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4579 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4580 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4581 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4582 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4583 if (depth == 1 && numFields < 2) { 4584 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 4585 PetscFunctionReturn(0); 4586 } 4587 /* Get points */ 4588 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4589 if (!clPoints) { 4590 PetscInt pStart, pEnd, p, q; 4591 4592 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4593 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4594 /* Compress out points not in the section */ 4595 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4596 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4597 points[q*2] = points[p]; 4598 points[q*2+1] = points[p+1]; 4599 ++q; 4600 } 4601 } 4602 numPoints = q; 4603 } else { 4604 PetscInt dof, off; 4605 4606 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4607 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4608 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4609 numPoints = dof/2; 4610 points = (PetscInt *) &clp[off]; 4611 } 4612 /* Get array */ 4613 if (!values || !*values) { 4614 PetscInt asize = 0, dof, p; 4615 4616 for (p = 0; p < numPoints*2; p += 2) { 4617 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4618 asize += dof; 4619 } 4620 if (!values) { 4621 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4622 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4623 if (csize) *csize = asize; 4624 PetscFunctionReturn(0); 4625 } 4626 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 4627 } else { 4628 array = *values; 4629 } 4630 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 4631 /* Get values */ 4632 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, vArray, &size, array);CHKERRQ(ierr);} 4633 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, vArray, &size, array);CHKERRQ(ierr);} 4634 /* Cleanup points */ 4635 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4636 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4637 /* Cleanup array */ 4638 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 4639 if (!*values) { 4640 if (csize) *csize = size; 4641 *values = array; 4642 } else { 4643 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 4644 *csize = size; 4645 } 4646 PetscFunctionReturn(0); 4647 } 4648 4649 #undef __FUNCT__ 4650 #define __FUNCT__ "DMPlexVecRestoreClosure" 4651 /*@C 4652 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 4653 4654 Not collective 4655 4656 Input Parameters: 4657 + dm - The DM 4658 . section - The section describing the layout in v, or NULL to use the default section 4659 . v - The local vector 4660 . point - The sieve point in the DM 4661 . csize - The number of values in the closure, or NULL 4662 - values - The array of values, which is a borrowed array and should not be freed 4663 4664 Fortran Notes: 4665 Since it returns an array, this routine is only available in Fortran 90, and you must 4666 include petsc.h90 in your code. 4667 4668 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4669 4670 Level: intermediate 4671 4672 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4673 @*/ 4674 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4675 { 4676 PetscInt size = 0; 4677 PetscErrorCode ierr; 4678 4679 PetscFunctionBegin; 4680 /* Should work without recalculating size */ 4681 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 4682 PetscFunctionReturn(0); 4683 } 4684 4685 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 4686 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 4687 4688 #undef __FUNCT__ 4689 #define __FUNCT__ "updatePoint_private" 4690 PETSC_STATIC_INLINE PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 4691 { 4692 PetscInt cdof; /* The number of constraints on this point */ 4693 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4694 PetscScalar *a; 4695 PetscInt off, cind = 0, k; 4696 PetscErrorCode ierr; 4697 4698 PetscFunctionBegin; 4699 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4700 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4701 a = &array[off]; 4702 if (!cdof || setBC) { 4703 if (orientation >= 0) { 4704 for (k = 0; k < dof; ++k) { 4705 fuse(&a[k], values[k]); 4706 } 4707 } else { 4708 for (k = 0; k < dof; ++k) { 4709 fuse(&a[k], values[dof-k-1]); 4710 } 4711 } 4712 } else { 4713 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4714 if (orientation >= 0) { 4715 for (k = 0; k < dof; ++k) { 4716 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4717 fuse(&a[k], values[k]); 4718 } 4719 } else { 4720 for (k = 0; k < dof; ++k) { 4721 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4722 fuse(&a[k], values[dof-k-1]); 4723 } 4724 } 4725 } 4726 PetscFunctionReturn(0); 4727 } 4728 4729 #undef __FUNCT__ 4730 #define __FUNCT__ "updatePointBC_private" 4731 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 4732 { 4733 PetscInt cdof; /* The number of constraints on this point */ 4734 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4735 PetscScalar *a; 4736 PetscInt off, cind = 0, k; 4737 PetscErrorCode ierr; 4738 4739 PetscFunctionBegin; 4740 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4741 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4742 a = &array[off]; 4743 if (cdof) { 4744 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4745 if (orientation >= 0) { 4746 for (k = 0; k < dof; ++k) { 4747 if ((cind < cdof) && (k == cdofs[cind])) { 4748 fuse(&a[k], values[k]); 4749 ++cind; 4750 } 4751 } 4752 } else { 4753 for (k = 0; k < dof; ++k) { 4754 if ((cind < cdof) && (k == cdofs[cind])) { 4755 fuse(&a[k], values[dof-k-1]); 4756 ++cind; 4757 } 4758 } 4759 } 4760 } 4761 PetscFunctionReturn(0); 4762 } 4763 4764 #undef __FUNCT__ 4765 #define __FUNCT__ "updatePointFields_private" 4766 PETSC_STATIC_INLINE PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 4767 { 4768 PetscScalar *a; 4769 PetscInt fdof, foff, fcdof, foffset = *offset; 4770 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4771 PetscInt cind = 0, k, c; 4772 PetscErrorCode ierr; 4773 4774 PetscFunctionBegin; 4775 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4776 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4777 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4778 a = &array[foff]; 4779 if (!fcdof || setBC) { 4780 if (o >= 0) { 4781 for (k = 0; k < fdof; ++k) fuse(&a[k], values[foffset+k]); 4782 } else { 4783 for (k = fdof/fcomp-1; k >= 0; --k) { 4784 for (c = 0; c < fcomp; ++c) { 4785 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 4786 } 4787 } 4788 } 4789 } else { 4790 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4791 if (o >= 0) { 4792 for (k = 0; k < fdof; ++k) { 4793 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 4794 fuse(&a[k], values[foffset+k]); 4795 } 4796 } else { 4797 for (k = fdof/fcomp-1; k >= 0; --k) { 4798 for (c = 0; c < fcomp; ++c) { 4799 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 4800 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 4801 } 4802 } 4803 } 4804 } 4805 *offset += fdof; 4806 PetscFunctionReturn(0); 4807 } 4808 4809 #undef __FUNCT__ 4810 #define __FUNCT__ "updatePointFieldsBC_private" 4811 PETSC_STATIC_INLINE PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 4812 { 4813 PetscScalar *a; 4814 PetscInt fdof, foff, fcdof, foffset = *offset; 4815 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4816 PetscInt cind = 0, k, c; 4817 PetscErrorCode ierr; 4818 4819 PetscFunctionBegin; 4820 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4821 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4822 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4823 a = &array[foff]; 4824 if (fcdof) { 4825 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4826 if (o >= 0) { 4827 for (k = 0; k < fdof; ++k) { 4828 if ((cind < fcdof) && (k == fcdofs[cind])) { 4829 fuse(&a[k], values[foffset+k]); 4830 ++cind; 4831 } 4832 } 4833 } else { 4834 for (k = fdof/fcomp-1; k >= 0; --k) { 4835 for (c = 0; c < fcomp; ++c) { 4836 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 4837 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 4838 ++cind; 4839 } 4840 } 4841 } 4842 } 4843 } 4844 *offset += fdof; 4845 PetscFunctionReturn(0); 4846 } 4847 4848 #undef __FUNCT__ 4849 #define __FUNCT__ "DMPlexVecSetClosure_Static" 4850 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4851 { 4852 PetscScalar *array; 4853 const PetscInt *cone, *coneO; 4854 PetscInt pStart, pEnd, p, numPoints, off, dof; 4855 PetscErrorCode ierr; 4856 4857 PetscFunctionBeginHot; 4858 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4859 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4860 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4861 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4862 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4863 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 4864 const PetscInt cp = !p ? point : cone[p-1]; 4865 const PetscInt o = !p ? 0 : coneO[p-1]; 4866 4867 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 4868 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4869 /* ADD_VALUES */ 4870 { 4871 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4872 PetscScalar *a; 4873 PetscInt cdof, coff, cind = 0, k; 4874 4875 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 4876 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 4877 a = &array[coff]; 4878 if (!cdof) { 4879 if (o >= 0) { 4880 for (k = 0; k < dof; ++k) { 4881 a[k] += values[off+k]; 4882 } 4883 } else { 4884 for (k = 0; k < dof; ++k) { 4885 a[k] += values[off+dof-k-1]; 4886 } 4887 } 4888 } else { 4889 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 4890 if (o >= 0) { 4891 for (k = 0; k < dof; ++k) { 4892 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4893 a[k] += values[off+k]; 4894 } 4895 } else { 4896 for (k = 0; k < dof; ++k) { 4897 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4898 a[k] += values[off+dof-k-1]; 4899 } 4900 } 4901 } 4902 } 4903 } 4904 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4905 PetscFunctionReturn(0); 4906 } 4907 4908 #undef __FUNCT__ 4909 #define __FUNCT__ "DMPlexVecSetClosure" 4910 /*@C 4911 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 4912 4913 Not collective 4914 4915 Input Parameters: 4916 + dm - The DM 4917 . section - The section describing the layout in v, or NULL to use the default section 4918 . v - The local vector 4919 . point - The sieve point in the DM 4920 . values - The array of values 4921 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4922 4923 Fortran Notes: 4924 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4925 4926 Level: intermediate 4927 4928 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 4929 @*/ 4930 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4931 { 4932 PetscSection clSection; 4933 IS clPoints; 4934 PetscScalar *array; 4935 PetscInt *points = NULL; 4936 const PetscInt *clp; 4937 PetscInt depth, numFields, numPoints, p; 4938 PetscErrorCode ierr; 4939 4940 PetscFunctionBeginHot; 4941 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4942 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4943 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4944 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4945 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4946 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4947 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 4948 ierr = DMPlexVecSetClosure_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 4949 PetscFunctionReturn(0); 4950 } 4951 /* Get points */ 4952 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4953 if (!clPoints) { 4954 PetscInt pStart, pEnd, q; 4955 4956 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4957 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4958 /* Compress out points not in the section */ 4959 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4960 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4961 points[q*2] = points[p]; 4962 points[q*2+1] = points[p+1]; 4963 ++q; 4964 } 4965 } 4966 numPoints = q; 4967 } else { 4968 PetscInt dof, off; 4969 4970 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4971 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4972 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4973 numPoints = dof/2; 4974 points = (PetscInt *) &clp[off]; 4975 } 4976 /* Get array */ 4977 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4978 /* Get values */ 4979 if (numFields > 0) { 4980 PetscInt offset = 0, fcomp, f; 4981 for (f = 0; f < numFields; ++f) { 4982 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4983 switch (mode) { 4984 case INSERT_VALUES: 4985 for (p = 0; p < numPoints*2; p += 2) { 4986 const PetscInt point = points[p]; 4987 const PetscInt o = points[p+1]; 4988 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 4989 } break; 4990 case INSERT_ALL_VALUES: 4991 for (p = 0; p < numPoints*2; p += 2) { 4992 const PetscInt point = points[p]; 4993 const PetscInt o = points[p+1]; 4994 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 4995 } break; 4996 case INSERT_BC_VALUES: 4997 for (p = 0; p < numPoints*2; p += 2) { 4998 const PetscInt point = points[p]; 4999 const PetscInt o = points[p+1]; 5000 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 5001 } break; 5002 case ADD_VALUES: 5003 for (p = 0; p < numPoints*2; p += 2) { 5004 const PetscInt point = points[p]; 5005 const PetscInt o = points[p+1]; 5006 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 5007 } break; 5008 case ADD_ALL_VALUES: 5009 for (p = 0; p < numPoints*2; p += 2) { 5010 const PetscInt point = points[p]; 5011 const PetscInt o = points[p+1]; 5012 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 5013 } break; 5014 default: 5015 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 5016 } 5017 } 5018 } else { 5019 PetscInt dof, off; 5020 5021 switch (mode) { 5022 case INSERT_VALUES: 5023 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 5024 PetscInt o = points[p+1]; 5025 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5026 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 5027 } break; 5028 case INSERT_ALL_VALUES: 5029 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 5030 PetscInt o = points[p+1]; 5031 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5032 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 5033 } break; 5034 case INSERT_BC_VALUES: 5035 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 5036 PetscInt o = points[p+1]; 5037 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5038 updatePointBC_private(section, points[p], dof, insert, o, &values[off], array); 5039 } break; 5040 case ADD_VALUES: 5041 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 5042 PetscInt o = points[p+1]; 5043 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5044 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 5045 } break; 5046 case ADD_ALL_VALUES: 5047 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 5048 PetscInt o = points[p+1]; 5049 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5050 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 5051 } break; 5052 default: 5053 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 5054 } 5055 } 5056 /* Cleanup points */ 5057 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 5058 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 5059 /* Cleanup array */ 5060 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5061 PetscFunctionReturn(0); 5062 } 5063 5064 #undef __FUNCT__ 5065 #define __FUNCT__ "DMPlexPrintMatSetValues" 5066 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 5067 { 5068 PetscMPIInt rank; 5069 PetscInt i, j; 5070 PetscErrorCode ierr; 5071 5072 PetscFunctionBegin; 5073 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 5074 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 5075 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 5076 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 5077 numCIndices = numCIndices ? numCIndices : numRIndices; 5078 for (i = 0; i < numRIndices; i++) { 5079 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 5080 for (j = 0; j < numCIndices; j++) { 5081 #if defined(PETSC_USE_COMPLEX) 5082 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 5083 #else 5084 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 5085 #endif 5086 } 5087 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 5088 } 5089 PetscFunctionReturn(0); 5090 } 5091 5092 #undef __FUNCT__ 5093 #define __FUNCT__ "indicesPoint_private" 5094 /* . off - The global offset of this point */ 5095 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 5096 { 5097 PetscInt dof; /* The number of unknowns on this point */ 5098 PetscInt cdof; /* The number of constraints on this point */ 5099 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5100 PetscInt cind = 0, k; 5101 PetscErrorCode ierr; 5102 5103 PetscFunctionBegin; 5104 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5105 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5106 if (!cdof || setBC) { 5107 if (orientation >= 0) { 5108 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 5109 } else { 5110 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 5111 } 5112 } else { 5113 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5114 if (orientation >= 0) { 5115 for (k = 0; k < dof; ++k) { 5116 if ((cind < cdof) && (k == cdofs[cind])) { 5117 /* Insert check for returning constrained indices */ 5118 indices[*loff+k] = -(off+k+1); 5119 ++cind; 5120 } else { 5121 indices[*loff+k] = off+k-cind; 5122 } 5123 } 5124 } else { 5125 for (k = 0; k < dof; ++k) { 5126 if ((cind < cdof) && (k == cdofs[cind])) { 5127 /* Insert check for returning constrained indices */ 5128 indices[*loff+dof-k-1] = -(off+k+1); 5129 ++cind; 5130 } else { 5131 indices[*loff+dof-k-1] = off+k-cind; 5132 } 5133 } 5134 } 5135 } 5136 *loff += dof; 5137 PetscFunctionReturn(0); 5138 } 5139 5140 #undef __FUNCT__ 5141 #define __FUNCT__ "indicesPointFields_private" 5142 /* . off - The global offset of this point */ 5143 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 5144 { 5145 PetscInt numFields, foff, f; 5146 PetscErrorCode ierr; 5147 5148 PetscFunctionBegin; 5149 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5150 for (f = 0, foff = 0; f < numFields; ++f) { 5151 PetscInt fdof, fcomp, cfdof; 5152 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5153 PetscInt cind = 0, k, c; 5154 5155 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 5156 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5157 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 5158 if (!cfdof || setBC) { 5159 if (orientation >= 0) { 5160 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 5161 } else { 5162 for (k = fdof/fcomp-1; k >= 0; --k) { 5163 for (c = 0; c < fcomp; ++c) { 5164 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 5165 } 5166 } 5167 } 5168 } else { 5169 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5170 if (orientation >= 0) { 5171 for (k = 0; k < fdof; ++k) { 5172 if ((cind < cfdof) && (k == fcdofs[cind])) { 5173 indices[foffs[f]+k] = -(off+foff+k+1); 5174 ++cind; 5175 } else { 5176 indices[foffs[f]+k] = off+foff+k-cind; 5177 } 5178 } 5179 } else { 5180 for (k = fdof/fcomp-1; k >= 0; --k) { 5181 for (c = 0; c < fcomp; ++c) { 5182 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 5183 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 5184 ++cind; 5185 } else { 5186 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 5187 } 5188 } 5189 } 5190 } 5191 } 5192 foff += fdof - cfdof; 5193 foffs[f] += fdof; 5194 } 5195 PetscFunctionReturn(0); 5196 } 5197 5198 #undef __FUNCT__ 5199 #define __FUNCT__ "DMPlexMatSetClosure" 5200 /*@C 5201 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 5202 5203 Not collective 5204 5205 Input Parameters: 5206 + dm - The DM 5207 . section - The section describing the layout in v, or NULL to use the default section 5208 . globalSection - The section describing the layout in v, or NULL to use the default global section 5209 . A - The matrix 5210 . point - The sieve point in the DM 5211 . values - The array of values 5212 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 5213 5214 Fortran Notes: 5215 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5216 5217 Level: intermediate 5218 5219 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 5220 @*/ 5221 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5222 { 5223 DM_Plex *mesh = (DM_Plex*) dm->data; 5224 PetscSection clSection; 5225 IS clPoints; 5226 PetscInt *points = NULL; 5227 const PetscInt *clp; 5228 PetscInt *indices; 5229 PetscInt offsets[32]; 5230 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 5231 PetscErrorCode ierr; 5232 5233 PetscFunctionBegin; 5234 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5235 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 5236 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5237 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 5238 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5239 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 5240 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5241 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5242 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5243 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 5244 if (!clPoints) { 5245 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5246 /* Compress out points not in the section */ 5247 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5248 for (p = 0, q = 0; p < numPoints*2; p += 2) { 5249 if ((points[p] >= pStart) && (points[p] < pEnd)) { 5250 points[q*2] = points[p]; 5251 points[q*2+1] = points[p+1]; 5252 ++q; 5253 } 5254 } 5255 numPoints = q; 5256 } else { 5257 PetscInt dof, off; 5258 5259 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 5260 numPoints = dof/2; 5261 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 5262 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 5263 points = (PetscInt *) &clp[off]; 5264 } 5265 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 5266 PetscInt fdof; 5267 5268 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5269 for (f = 0; f < numFields; ++f) { 5270 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5271 offsets[f+1] += fdof; 5272 } 5273 numIndices += dof; 5274 } 5275 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 5276 5277 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 5278 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 5279 if (numFields) { 5280 for (p = 0; p < numPoints*2; p += 2) { 5281 PetscInt o = points[p+1]; 5282 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5283 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 5284 } 5285 } else { 5286 for (p = 0, off = 0; p < numPoints*2; p += 2) { 5287 PetscInt o = points[p+1]; 5288 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5289 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 5290 } 5291 } 5292 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 5293 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 5294 if (ierr) { 5295 PetscMPIInt rank; 5296 PetscErrorCode ierr2; 5297 5298 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5299 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5300 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 5301 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 5302 CHKERRQ(ierr); 5303 } 5304 if (!clPoints) { 5305 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5306 } else { 5307 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 5308 } 5309 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 5310 PetscFunctionReturn(0); 5311 } 5312 5313 #undef __FUNCT__ 5314 #define __FUNCT__ "DMPlexMatSetClosureRefined" 5315 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5316 { 5317 DM_Plex *mesh = (DM_Plex*) dmf->data; 5318 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5319 PetscInt *cpoints = NULL; 5320 PetscInt *findices, *cindices; 5321 PetscInt foffsets[32], coffsets[32]; 5322 CellRefiner cellRefiner; 5323 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5324 PetscErrorCode ierr; 5325 5326 PetscFunctionBegin; 5327 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5328 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5329 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5330 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5331 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5332 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5333 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5334 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5335 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5336 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5337 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 5338 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5339 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5340 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5341 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5342 /* Column indices */ 5343 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5344 maxFPoints = numCPoints; 5345 /* Compress out points not in the section */ 5346 /* TODO: Squeeze out points with 0 dof as well */ 5347 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5348 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5349 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5350 cpoints[q*2] = cpoints[p]; 5351 cpoints[q*2+1] = cpoints[p+1]; 5352 ++q; 5353 } 5354 } 5355 numCPoints = q; 5356 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5357 PetscInt fdof; 5358 5359 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5360 if (!dof) continue; 5361 for (f = 0; f < numFields; ++f) { 5362 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5363 coffsets[f+1] += fdof; 5364 } 5365 numCIndices += dof; 5366 } 5367 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5368 /* Row indices */ 5369 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5370 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5371 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5372 for (r = 0, q = 0; r < numSubcells; ++r) { 5373 /* TODO Map from coarse to fine cells */ 5374 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5375 /* Compress out points not in the section */ 5376 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5377 for (p = 0; p < numFPoints*2; p += 2) { 5378 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5379 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5380 if (!dof) continue; 5381 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5382 if (s < q) continue; 5383 ftotpoints[q*2] = fpoints[p]; 5384 ftotpoints[q*2+1] = fpoints[p+1]; 5385 ++q; 5386 } 5387 } 5388 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5389 } 5390 numFPoints = q; 5391 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5392 PetscInt fdof; 5393 5394 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5395 if (!dof) continue; 5396 for (f = 0; f < numFields; ++f) { 5397 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5398 foffsets[f+1] += fdof; 5399 } 5400 numFIndices += dof; 5401 } 5402 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5403 5404 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5405 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5406 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5407 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5408 if (numFields) { 5409 for (p = 0; p < numFPoints*2; p += 2) { 5410 PetscInt o = ftotpoints[p+1]; 5411 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5412 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5413 } 5414 for (p = 0; p < numCPoints*2; p += 2) { 5415 PetscInt o = cpoints[p+1]; 5416 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5417 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5418 } 5419 } else { 5420 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5421 PetscInt o = ftotpoints[p+1]; 5422 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5423 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5424 } 5425 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5426 PetscInt o = cpoints[p+1]; 5427 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5428 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5429 } 5430 } 5431 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5432 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5433 if (ierr) { 5434 PetscMPIInt rank; 5435 PetscErrorCode ierr2; 5436 5437 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5438 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5439 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5440 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 5441 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 5442 CHKERRQ(ierr); 5443 } 5444 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5445 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5446 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5447 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5448 PetscFunctionReturn(0); 5449 } 5450 5451 #undef __FUNCT__ 5452 #define __FUNCT__ "DMPlexGetHybridBounds" 5453 /*@ 5454 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5455 5456 Input Parameter: 5457 . dm - The DMPlex object 5458 5459 Output Parameters: 5460 + cMax - The first hybrid cell 5461 . cMax - The first hybrid face 5462 . cMax - The first hybrid edge 5463 - cMax - The first hybrid vertex 5464 5465 Level: developer 5466 5467 .seealso DMPlexCreateHybridMesh() 5468 @*/ 5469 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5470 { 5471 DM_Plex *mesh = (DM_Plex*) dm->data; 5472 PetscInt dim; 5473 PetscErrorCode ierr; 5474 5475 PetscFunctionBegin; 5476 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5477 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5478 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5479 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5480 if (eMax) *eMax = mesh->hybridPointMax[1]; 5481 if (vMax) *vMax = mesh->hybridPointMax[0]; 5482 PetscFunctionReturn(0); 5483 } 5484 5485 #undef __FUNCT__ 5486 #define __FUNCT__ "DMPlexSetHybridBounds" 5487 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 5488 { 5489 DM_Plex *mesh = (DM_Plex*) dm->data; 5490 PetscInt dim; 5491 PetscErrorCode ierr; 5492 5493 PetscFunctionBegin; 5494 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5495 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5496 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 5497 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 5498 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 5499 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 5500 PetscFunctionReturn(0); 5501 } 5502 5503 #undef __FUNCT__ 5504 #define __FUNCT__ "DMPlexGetVTKCellHeight" 5505 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 5506 { 5507 DM_Plex *mesh = (DM_Plex*) dm->data; 5508 5509 PetscFunctionBegin; 5510 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5511 PetscValidPointer(cellHeight, 2); 5512 *cellHeight = mesh->vtkCellHeight; 5513 PetscFunctionReturn(0); 5514 } 5515 5516 #undef __FUNCT__ 5517 #define __FUNCT__ "DMPlexSetVTKCellHeight" 5518 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 5519 { 5520 DM_Plex *mesh = (DM_Plex*) dm->data; 5521 5522 PetscFunctionBegin; 5523 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5524 mesh->vtkCellHeight = cellHeight; 5525 PetscFunctionReturn(0); 5526 } 5527 5528 #undef __FUNCT__ 5529 #define __FUNCT__ "DMPlexCreateNumbering_Private" 5530 /* We can easily have a form that takes an IS instead */ 5531 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 5532 { 5533 PetscSection section, globalSection; 5534 PetscInt *numbers, p; 5535 PetscErrorCode ierr; 5536 5537 PetscFunctionBegin; 5538 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5539 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 5540 for (p = pStart; p < pEnd; ++p) { 5541 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 5542 } 5543 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 5544 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 5545 ierr = PetscMalloc1((pEnd - pStart), &numbers);CHKERRQ(ierr); 5546 for (p = pStart; p < pEnd; ++p) { 5547 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 5548 } 5549 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 5550 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5551 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 5552 PetscFunctionReturn(0); 5553 } 5554 5555 #undef __FUNCT__ 5556 #define __FUNCT__ "DMPlexGetCellNumbering" 5557 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 5558 { 5559 DM_Plex *mesh = (DM_Plex*) dm->data; 5560 PetscInt cellHeight, cStart, cEnd, cMax; 5561 PetscErrorCode ierr; 5562 5563 PetscFunctionBegin; 5564 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5565 if (!mesh->globalCellNumbers) { 5566 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 5567 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5568 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5569 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 5570 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 5571 } 5572 *globalCellNumbers = mesh->globalCellNumbers; 5573 PetscFunctionReturn(0); 5574 } 5575 5576 #undef __FUNCT__ 5577 #define __FUNCT__ "DMPlexGetVertexNumbering" 5578 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 5579 { 5580 DM_Plex *mesh = (DM_Plex*) dm->data; 5581 PetscInt vStart, vEnd, vMax; 5582 PetscErrorCode ierr; 5583 5584 PetscFunctionBegin; 5585 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5586 if (!mesh->globalVertexNumbers) { 5587 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5588 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 5589 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 5590 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 5591 } 5592 *globalVertexNumbers = mesh->globalVertexNumbers; 5593 PetscFunctionReturn(0); 5594 } 5595 5596 5597 #undef __FUNCT__ 5598 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 5599 /*@C 5600 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 5601 the local section and an SF describing the section point overlap. 5602 5603 Input Parameters: 5604 + s - The PetscSection for the local field layout 5605 . sf - The SF describing parallel layout of the section points 5606 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 5607 . label - The label specifying the points 5608 - labelValue - The label stratum specifying the points 5609 5610 Output Parameter: 5611 . gsection - The PetscSection for the global field layout 5612 5613 Note: This gives negative sizes and offsets to points not owned by this process 5614 5615 Level: developer 5616 5617 .seealso: PetscSectionCreate() 5618 @*/ 5619 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 5620 { 5621 PetscInt *neg = NULL, *tmpOff = NULL; 5622 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 5623 PetscErrorCode ierr; 5624 5625 PetscFunctionBegin; 5626 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 5627 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 5628 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 5629 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 5630 if (nroots >= 0) { 5631 if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart); 5632 ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr); 5633 if (nroots > pEnd-pStart) { 5634 ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr); 5635 } else { 5636 tmpOff = &(*gsection)->atlasDof[-pStart]; 5637 } 5638 } 5639 /* Mark ghost points with negative dof */ 5640 for (p = pStart; p < pEnd; ++p) { 5641 PetscInt value; 5642 5643 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 5644 if (value != labelValue) continue; 5645 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 5646 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 5647 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 5648 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 5649 if (neg) neg[p] = -(dof+1); 5650 } 5651 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 5652 if (nroots >= 0) { 5653 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5654 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5655 if (nroots > pEnd-pStart) { 5656 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} 5657 } 5658 } 5659 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 5660 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5661 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 5662 (*gsection)->atlasOff[p] = off; 5663 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 5664 } 5665 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 5666 globalOff -= off; 5667 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5668 (*gsection)->atlasOff[p] += globalOff; 5669 if (neg) neg[p] = -((*gsection)->atlasOff[p]+1); 5670 } 5671 /* Put in negative offsets for ghost points */ 5672 if (nroots >= 0) { 5673 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5674 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5675 if (nroots > pEnd-pStart) { 5676 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} 5677 } 5678 } 5679 if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);} 5680 ierr = PetscFree(neg);CHKERRQ(ierr); 5681 PetscFunctionReturn(0); 5682 } 5683 5684 #undef __FUNCT__ 5685 #define __FUNCT__ "DMPlexCheckSymmetry" 5686 /*@ 5687 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5688 5689 Input Parameters: 5690 + dm - The DMPlex object 5691 5692 Note: This is a useful diagnostic when creating meshes programmatically. 5693 5694 Level: developer 5695 5696 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5697 @*/ 5698 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5699 { 5700 PetscSection coneSection, supportSection; 5701 const PetscInt *cone, *support; 5702 PetscInt coneSize, c, supportSize, s; 5703 PetscInt pStart, pEnd, p, csize, ssize; 5704 PetscErrorCode ierr; 5705 5706 PetscFunctionBegin; 5707 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5708 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5709 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5710 /* Check that point p is found in the support of its cone points, and vice versa */ 5711 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5712 for (p = pStart; p < pEnd; ++p) { 5713 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5714 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5715 for (c = 0; c < coneSize; ++c) { 5716 PetscBool dup = PETSC_FALSE; 5717 PetscInt d; 5718 for (d = c-1; d >= 0; --d) { 5719 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5720 } 5721 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5722 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5723 for (s = 0; s < supportSize; ++s) { 5724 if (support[s] == p) break; 5725 } 5726 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5727 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p); 5728 for (s = 0; s < coneSize; ++s) { 5729 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]); 5730 } 5731 ierr = PetscPrintf(PETSC_COMM_SELF, "\n"); 5732 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]); 5733 for (s = 0; s < supportSize; ++s) { 5734 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]); 5735 } 5736 ierr = PetscPrintf(PETSC_COMM_SELF, "\n"); 5737 if (dup) { 5738 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5739 } else { 5740 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5741 } 5742 } 5743 } 5744 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5745 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5746 for (s = 0; s < supportSize; ++s) { 5747 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5748 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5749 for (c = 0; c < coneSize; ++c) { 5750 if (cone[c] == p) break; 5751 } 5752 if (c >= coneSize) { 5753 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p); 5754 for (c = 0; c < supportSize; ++c) { 5755 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]); 5756 } 5757 ierr = PetscPrintf(PETSC_COMM_SELF, "\n"); 5758 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]); 5759 for (c = 0; c < coneSize; ++c) { 5760 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]); 5761 } 5762 ierr = PetscPrintf(PETSC_COMM_SELF, "\n"); 5763 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5764 } 5765 } 5766 } 5767 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5768 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5769 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5770 PetscFunctionReturn(0); 5771 } 5772 5773 #undef __FUNCT__ 5774 #define __FUNCT__ "DMPlexCheckSkeleton" 5775 /*@ 5776 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5777 5778 Input Parameters: 5779 + dm - The DMPlex object 5780 . isSimplex - Are the cells simplices or tensor products 5781 - cellHeight - Normally 0 5782 5783 Note: This is a useful diagnostic when creating meshes programmatically. 5784 5785 Level: developer 5786 5787 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5788 @*/ 5789 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5790 { 5791 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5792 PetscErrorCode ierr; 5793 5794 PetscFunctionBegin; 5795 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5796 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5797 switch (dim) { 5798 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5799 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5800 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5801 default: 5802 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5803 } 5804 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5805 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5806 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5807 cMax = cMax >= 0 ? cMax : cEnd; 5808 for (c = cStart; c < cMax; ++c) { 5809 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5810 5811 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5812 for (cl = 0; cl < closureSize*2; cl += 2) { 5813 const PetscInt p = closure[cl]; 5814 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5815 } 5816 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5817 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5818 } 5819 for (c = cMax; c < cEnd; ++c) { 5820 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5821 5822 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5823 for (cl = 0; cl < closureSize*2; cl += 2) { 5824 const PetscInt p = closure[cl]; 5825 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5826 } 5827 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5828 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5829 } 5830 PetscFunctionReturn(0); 5831 } 5832 5833 #undef __FUNCT__ 5834 #define __FUNCT__ "DMPlexCheckFaces" 5835 /*@ 5836 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5837 5838 Input Parameters: 5839 + dm - The DMPlex object 5840 . isSimplex - Are the cells simplices or tensor products 5841 - cellHeight - Normally 0 5842 5843 Note: This is a useful diagnostic when creating meshes programmatically. 5844 5845 Level: developer 5846 5847 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5848 @*/ 5849 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5850 { 5851 PetscInt pMax[4]; 5852 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5853 PetscErrorCode ierr; 5854 5855 PetscFunctionBegin; 5856 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5857 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5858 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5859 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5860 for (h = cellHeight; h < dim; ++h) { 5861 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5862 for (c = cStart; c < cEnd; ++c) { 5863 const PetscInt *cone, *ornt, *faces; 5864 PetscInt numFaces, faceSize, coneSize,f; 5865 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5866 5867 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5868 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5869 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5870 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5871 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5872 for (cl = 0; cl < closureSize*2; cl += 2) { 5873 const PetscInt p = closure[cl]; 5874 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5875 } 5876 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5877 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5878 for (f = 0; f < numFaces; ++f) { 5879 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5880 5881 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5882 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5883 const PetscInt p = fclosure[cl]; 5884 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5885 } 5886 if (fnumCorners != faceSize) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d (%d) of cell %d has %d vertices but should have %d", cone[f], f, c, fnumCorners, faceSize); 5887 for (v = 0; v < fnumCorners; ++v) { 5888 if (fclosure[v] != faces[f*faceSize+v]) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d (%d) of cell %d vertex %d, %d != %d", cone[f], f, c, v, fclosure[v], faces[f*faceSize+v]); 5889 } 5890 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5891 } 5892 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5893 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5894 } 5895 } 5896 PetscFunctionReturn(0); 5897 } 5898 5899 #undef __FUNCT__ 5900 #define __FUNCT__ "DMCreateInterpolation_Plex" 5901 /* Pointwise interpolation 5902 Just code FEM for now 5903 u^f = I u^c 5904 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5905 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5906 I_{ij} = psi^f_i phi^c_j 5907 */ 5908 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5909 { 5910 PetscSection gsc, gsf; 5911 PetscInt m, n; 5912 void *ctx; 5913 PetscErrorCode ierr; 5914 5915 PetscFunctionBegin; 5916 /* 5917 Loop over coarse cells 5918 Loop over coarse basis functions 5919 Loop over fine cells in coarse cell 5920 Loop over fine dual basis functions 5921 Evaluate coarse basis on fine dual basis quad points 5922 Sum 5923 Update local element matrix 5924 Accumulate to interpolation matrix 5925 5926 Can extend PetscFEIntegrateJacobian_Basic() to do a specialized cell loop 5927 */ 5928 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5929 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5930 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5931 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5932 /* We need to preallocate properly */ 5933 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5934 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5935 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5936 ierr = MatSetUp(*interpolation);CHKERRQ(ierr); 5937 ierr = MatSetFromOptions(*interpolation);CHKERRQ(ierr); 5938 ierr = MatSetOption(*interpolation, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);CHKERRQ(ierr); 5939 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5940 ierr = DMPlexComputeInterpolatorFEM(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr); 5941 /* Use naive scaling */ 5942 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5943 PetscFunctionReturn(0); 5944 } 5945 5946 #undef __FUNCT__ 5947 #define __FUNCT__ "DMCreateInjection_Plex" 5948 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, VecScatter *ctx) 5949 { 5950 Vec cv, fv; 5951 IS cis, fis, fpointIS; 5952 PetscSection sc, gsc, gsf; 5953 const PetscInt *fpoints; 5954 PetscInt *cindices, *findices; 5955 PetscInt cpStart, cpEnd, m, off, cp; 5956 PetscErrorCode ierr; 5957 5958 PetscFunctionBegin; 5959 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5960 ierr = DMGetGlobalVector(dmFine, &fv);CHKERRQ(ierr); 5961 ierr = DMGetDefaultSection(dmCoarse, &sc);CHKERRQ(ierr); 5962 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5963 ierr = DMGetGlobalVector(dmCoarse, &cv);CHKERRQ(ierr); 5964 ierr = DMPlexCreateCoarsePointIS(dmCoarse, &fpointIS);CHKERRQ(ierr); 5965 ierr = PetscSectionGetConstrainedStorageSize(gsc, &m);CHKERRQ(ierr); 5966 ierr = PetscMalloc2(m,&cindices,m,&findices);CHKERRQ(ierr); 5967 ierr = PetscSectionGetChart(gsc, &cpStart, &cpEnd);CHKERRQ(ierr); 5968 ierr = ISGetIndices(fpointIS, &fpoints);CHKERRQ(ierr); 5969 for (cp = cpStart, off = 0; cp < cpEnd; ++cp) { 5970 const PetscInt *cdofsC = NULL; 5971 PetscInt fp = fpoints[cp-cpStart], dofC, cdofC, dofF, offC, offF, d, e; 5972 5973 ierr = PetscSectionGetDof(gsc, cp, &dofC);CHKERRQ(ierr); 5974 if (dofC <= 0) continue; 5975 ierr = PetscSectionGetConstraintDof(sc, cp, &cdofC);CHKERRQ(ierr); 5976 ierr = PetscSectionGetDof(gsf, fp, &dofF);CHKERRQ(ierr); 5977 ierr = PetscSectionGetOffset(gsc, cp, &offC);CHKERRQ(ierr); 5978 ierr = PetscSectionGetOffset(gsf, fp, &offF);CHKERRQ(ierr); 5979 if (cdofC) {ierr = PetscSectionGetConstraintIndices(sc, cp, &cdofsC);CHKERRQ(ierr);} 5980 if (dofC != dofF) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %d (%d) has %d coarse dofs != %d fine dofs", cp, fp, dofC, dofF); 5981 if (offC < 0 || offF < 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Coarse point %d has invalid offset %d (%d)", cp, offC, offF); 5982 for (d = 0, e = 0; d < dofC; ++d) { 5983 if (cdofsC && cdofsC[e] == d) {++e; continue;} 5984 cindices[off+d-e] = offC+d; findices[off+d-e] = offF+d; 5985 } 5986 if (e != cdofC) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %d (%d) has invalid number of constraints %d != %d", cp, fp, e, cdofC); 5987 off += dofC-cdofC; 5988 } 5989 ierr = ISRestoreIndices(fpointIS, &fpoints);CHKERRQ(ierr); 5990 if (off != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of coarse dofs %d != %d", off, m); 5991 ierr = ISCreateGeneral(PETSC_COMM_SELF, m, cindices, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 5992 ierr = ISCreateGeneral(PETSC_COMM_SELF, m, findices, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 5993 ierr = VecScatterCreate(cv, cis, fv, fis, ctx);CHKERRQ(ierr); 5994 ierr = ISDestroy(&cis);CHKERRQ(ierr); 5995 ierr = ISDestroy(&fis);CHKERRQ(ierr); 5996 ierr = DMRestoreGlobalVector(dmFine, &fv);CHKERRQ(ierr); 5997 ierr = DMRestoreGlobalVector(dmCoarse, &cv);CHKERRQ(ierr); 5998 ierr = ISDestroy(&fpointIS);CHKERRQ(ierr); 5999 PetscFunctionReturn(0); 6000 } 6001 6002 #undef __FUNCT__ 6003 #define __FUNCT__ "DMCreateDefaultSection_Plex" 6004 /* Pointwise interpolation 6005 Just code FEM for now 6006 u^f = I u^c 6007 sum_k u^f_k phi^f_k = I sum_l u^c_l phi^c_l 6008 u^f_i = sum_l int psi^f_i I phi^c_l u^c_l 6009 I_{ij} = int psi^f_i phi^c_j 6010 */ 6011 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 6012 { 6013 PetscSection section; 6014 IS *bcPoints; 6015 PetscInt *bcFields, *numComp, *numDof; 6016 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc, f; 6017 PetscErrorCode ierr; 6018 6019 PetscFunctionBegin; 6020 /* Handle boundary conditions */ 6021 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6022 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6023 ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 6024 for (bd = 0; bd < numBd; ++bd) { 6025 PetscBool isEssential; 6026 ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6027 if (isEssential) ++numBC; 6028 } 6029 ierr = PetscMalloc2(numBC,&bcFields,numBC,&bcPoints);CHKERRQ(ierr); 6030 for (bd = 0, bc = 0; bd < numBd; ++bd) { 6031 const char *bdLabel; 6032 DMLabel label; 6033 const PetscInt *values; 6034 PetscInt field, numValues; 6035 PetscBool isEssential, has; 6036 6037 ierr = DMPlexGetBoundary(dm, bd, &isEssential, &bdLabel, &field, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 6038 if (numValues != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Bug me and I will fix this"); 6039 ierr = DMPlexHasLabel(dm, bdLabel, &has);CHKERRQ(ierr); 6040 if (!has) { 6041 ierr = DMPlexCreateLabel(dm, bdLabel);CHKERRQ(ierr); 6042 ierr = DMPlexGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 6043 ierr = DMPlexMarkBoundaryFaces(dm, label);CHKERRQ(ierr); 6044 } 6045 ierr = DMPlexGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 6046 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 6047 if (isEssential) { 6048 bcFields[bc] = field; 6049 ierr = DMPlexGetStratumIS(dm, bdLabel, values[0], &bcPoints[bc++]);CHKERRQ(ierr); 6050 } 6051 } 6052 /* Handle discretization */ 6053 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 6054 ierr = PetscMalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 6055 for (f = 0; f < numFields; ++f) { 6056 PetscFE fe; 6057 const PetscInt *numFieldDof; 6058 PetscInt d; 6059 6060 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 6061 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 6062 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 6063 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 6064 } 6065 for (f = 0; f < numFields; ++f) { 6066 PetscInt d; 6067 for (d = 1; d < dim; ++d) { 6068 if ((numDof[f*(dim+1)+d] > 0) && (depth < dim)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated when unknowns are specified on edges or faces."); 6069 } 6070 } 6071 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcPoints, §ion);CHKERRQ(ierr); 6072 for (f = 0; f < numFields; ++f) { 6073 PetscFE fe; 6074 const char *name; 6075 6076 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 6077 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 6078 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 6079 } 6080 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 6081 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6082 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);} 6083 ierr = PetscFree2(bcFields,bcPoints);CHKERRQ(ierr); 6084 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 6085 PetscFunctionReturn(0); 6086 } 6087 6088 #undef __FUNCT__ 6089 #define __FUNCT__ "DMPlexGetCoarseDM" 6090 /*@ 6091 DMPlexGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 6092 6093 Input Parameter: 6094 . dm - The DMPlex object 6095 6096 Output Parameter: 6097 . cdm - The coarse DM 6098 6099 Level: intermediate 6100 6101 .seealso: DMPlexSetCoarseDM() 6102 @*/ 6103 PetscErrorCode DMPlexGetCoarseDM(DM dm, DM *cdm) 6104 { 6105 PetscFunctionBegin; 6106 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6107 PetscValidPointer(cdm, 2); 6108 *cdm = ((DM_Plex *) dm->data)->coarseMesh; 6109 PetscFunctionReturn(0); 6110 } 6111 6112 #undef __FUNCT__ 6113 #define __FUNCT__ "DMPlexSetCoarseDM" 6114 /*@ 6115 DMPlexSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 6116 6117 Input Parameters: 6118 + dm - The DMPlex object 6119 - cdm - The coarse DM 6120 6121 Level: intermediate 6122 6123 .seealso: DMPlexGetCoarseDM() 6124 @*/ 6125 PetscErrorCode DMPlexSetCoarseDM(DM dm, DM cdm) 6126 { 6127 DM_Plex *mesh; 6128 PetscErrorCode ierr; 6129 6130 PetscFunctionBegin; 6131 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6132 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 6133 mesh = (DM_Plex *) dm->data; 6134 ierr = DMDestroy(&mesh->coarseMesh);CHKERRQ(ierr); 6135 mesh->coarseMesh = cdm; 6136 ierr = PetscObjectReference((PetscObject) mesh->coarseMesh);CHKERRQ(ierr); 6137 PetscFunctionReturn(0); 6138 } 6139