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