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