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