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