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, *pMax; 2670 PetscInt depth, pStart = 0, pEnd = 0; 2671 PetscInt p, d, dep, f; 2672 PetscBool *isFE; 2673 PetscErrorCode ierr; 2674 2675 PetscFunctionBegin; 2676 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 2677 for (f = 0; f < numFields; ++f) { 2678 PetscObject obj; 2679 PetscClassId id; 2680 2681 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 2682 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 2683 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 2684 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 2685 else {isFE[f] = PETSC_FALSE;} 2686 } 2687 ierr = PetscMalloc1(dim+1, &numDofTot);CHKERRQ(ierr); 2688 for (d = 0; d <= dim; ++d) { 2689 numDofTot[d] = 0; 2690 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 2691 } 2692 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2693 if (numFields > 0) { 2694 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 2695 if (numComp) { 2696 for (f = 0; f < numFields; ++f) { 2697 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 2698 } 2699 } 2700 } 2701 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2702 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 2703 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2704 ierr = PetscMalloc1(depth+1,&pMax);CHKERRQ(ierr); 2705 ierr = DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 2706 for (dep = 0; dep <= depth; ++dep) { 2707 d = dim == depth ? dep : (!dep ? 0 : dim); 2708 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 2709 pMax[dep] = pMax[dep] < 0 ? pEnd : pMax[dep]; 2710 for (p = pStart; p < pEnd; ++p) { 2711 for (f = 0; f < numFields; ++f) { 2712 if (isFE[f] && p >= pMax[dep]) continue; 2713 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 2714 } 2715 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 2716 } 2717 } 2718 ierr = PetscFree(pMax);CHKERRQ(ierr); 2719 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 2720 ierr = PetscFree(isFE);CHKERRQ(ierr); 2721 PetscFunctionReturn(0); 2722 } 2723 2724 #undef __FUNCT__ 2725 #define __FUNCT__ "DMPlexCreateSectionBCDof" 2726 /* Set the number of dof on each point and separate by fields 2727 If constDof is PETSC_DETERMINE, constrain every dof on the point 2728 */ 2729 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 2730 { 2731 PetscInt numFields; 2732 PetscInt bc; 2733 PetscSection aSec; 2734 PetscErrorCode ierr; 2735 2736 PetscFunctionBegin; 2737 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2738 for (bc = 0; bc < numBC; ++bc) { 2739 PetscInt field = 0; 2740 const PetscInt *idx; 2741 PetscInt n, i; 2742 2743 if (numFields) field = bcField[bc]; 2744 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 2745 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2746 for (i = 0; i < n; ++i) { 2747 const PetscInt p = idx[i]; 2748 PetscInt numConst = constDof; 2749 2750 /* Constrain every dof on the point */ 2751 if (numConst < 0) { 2752 if (numFields) { 2753 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 2754 } else { 2755 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 2756 } 2757 } 2758 if (numFields) { 2759 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 2760 } 2761 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 2762 } 2763 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2764 } 2765 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 2766 if (aSec) { 2767 PetscInt aStart, aEnd, a; 2768 2769 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 2770 for (a = aStart; a < aEnd; a++) { 2771 PetscInt dof; 2772 2773 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 2774 if (dof) { 2775 /* if there are point-to-point constraints, then all dofs are constrained */ 2776 ierr = PetscSectionGetDof(section, a, &dof);CHKERRQ(ierr); 2777 ierr = PetscSectionSetConstraintDof(section, a, dof);CHKERRQ(ierr); 2778 if (numFields) { 2779 PetscInt f; 2780 2781 for (f = 0; f < numFields; f++) { 2782 ierr = PetscSectionGetFieldDof(section, a, f, &dof);CHKERRQ(ierr); 2783 ierr = PetscSectionSetFieldConstraintDof(section, a, f, dof);CHKERRQ(ierr); 2784 } 2785 } 2786 } 2787 } 2788 } 2789 PetscFunctionReturn(0); 2790 } 2791 2792 #undef __FUNCT__ 2793 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 2794 /* Set the constrained indices on each point and separate by fields */ 2795 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 2796 { 2797 PetscInt *maxConstraints; 2798 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 2799 PetscErrorCode ierr; 2800 2801 PetscFunctionBegin; 2802 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2803 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 2804 ierr = PetscMalloc1(numFields+1, &maxConstraints);CHKERRQ(ierr); 2805 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 2806 for (p = pStart; p < pEnd; ++p) { 2807 PetscInt cdof; 2808 2809 if (numFields) { 2810 for (f = 0; f < numFields; ++f) { 2811 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 2812 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 2813 } 2814 } else { 2815 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 2816 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 2817 } 2818 } 2819 for (f = 0; f < numFields; ++f) { 2820 maxConstraints[numFields] += maxConstraints[f]; 2821 } 2822 if (maxConstraints[numFields]) { 2823 PetscInt *indices; 2824 2825 ierr = PetscMalloc1(maxConstraints[numFields], &indices);CHKERRQ(ierr); 2826 for (p = pStart; p < pEnd; ++p) { 2827 PetscInt cdof, d; 2828 2829 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 2830 if (cdof) { 2831 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 2832 if (numFields) { 2833 PetscInt numConst = 0, foff = 0; 2834 2835 for (f = 0; f < numFields; ++f) { 2836 PetscInt cfdof, fdof; 2837 2838 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 2839 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 2840 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 2841 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 2842 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 2843 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 2844 numConst += cfdof; 2845 foff += fdof; 2846 } 2847 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 2848 } else { 2849 for (d = 0; d < cdof; ++d) indices[d] = d; 2850 } 2851 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 2852 } 2853 } 2854 ierr = PetscFree(indices);CHKERRQ(ierr); 2855 } 2856 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 2857 PetscFunctionReturn(0); 2858 } 2859 2860 #undef __FUNCT__ 2861 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 2862 /* Set the constrained field indices on each point */ 2863 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 2864 { 2865 const PetscInt *points, *indices; 2866 PetscInt numFields, maxDof, numPoints, p, numConstraints; 2867 PetscErrorCode ierr; 2868 2869 PetscFunctionBegin; 2870 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2871 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 2872 2873 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 2874 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 2875 if (!constraintIndices) { 2876 PetscInt *idx, i; 2877 2878 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 2879 ierr = PetscMalloc1(maxDof, &idx);CHKERRQ(ierr); 2880 for (i = 0; i < maxDof; ++i) idx[i] = i; 2881 for (p = 0; p < numPoints; ++p) { 2882 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 2883 } 2884 ierr = PetscFree(idx);CHKERRQ(ierr); 2885 } else { 2886 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 2887 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 2888 for (p = 0; p < numPoints; ++p) { 2889 PetscInt fcdof; 2890 2891 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 2892 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); 2893 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 2894 } 2895 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 2896 } 2897 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 2898 PetscFunctionReturn(0); 2899 } 2900 2901 #undef __FUNCT__ 2902 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 2903 /* Set the constrained indices on each point and separate by fields */ 2904 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 2905 { 2906 PetscInt *indices; 2907 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 2908 PetscErrorCode ierr; 2909 2910 PetscFunctionBegin; 2911 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 2912 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 2913 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2914 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 2915 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 2916 for (p = pStart; p < pEnd; ++p) { 2917 PetscInt cdof, d; 2918 2919 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 2920 if (cdof) { 2921 PetscInt numConst = 0, foff = 0; 2922 2923 for (f = 0; f < numFields; ++f) { 2924 const PetscInt *fcind; 2925 PetscInt fdof, fcdof; 2926 2927 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 2928 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 2929 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 2930 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 2931 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 2932 foff += fdof; 2933 numConst += fcdof; 2934 } 2935 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 2936 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 2937 } 2938 } 2939 ierr = PetscFree(indices);CHKERRQ(ierr); 2940 PetscFunctionReturn(0); 2941 } 2942 2943 #undef __FUNCT__ 2944 #define __FUNCT__ "DMPlexCreateSection" 2945 /*@C 2946 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 2947 2948 Not Collective 2949 2950 Input Parameters: 2951 + dm - The DMPlex object 2952 . dim - The spatial dimension of the problem 2953 . numFields - The number of fields in the problem 2954 . numComp - An array of size numFields that holds the number of components for each field 2955 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 2956 . numBC - The number of boundary conditions 2957 . bcField - An array of size numBC giving the field number for each boundry condition 2958 . bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 2959 - perm - Optional permutation of the chart, or NULL 2960 2961 Output Parameter: 2962 . section - The PetscSection object 2963 2964 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 2965 number of dof for field 0 on each edge. 2966 2967 The chart permutation is the same one set using PetscSectionSetPermutation() 2968 2969 Level: developer 2970 2971 Fortran Notes: 2972 A Fortran 90 version is available as DMPlexCreateSectionF90() 2973 2974 .keywords: mesh, elements 2975 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 2976 @*/ 2977 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) 2978 { 2979 PetscSection aSec; 2980 PetscErrorCode ierr; 2981 2982 PetscFunctionBegin; 2983 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 2984 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 2985 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 2986 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 2987 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 2988 if (numBC || aSec) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 2989 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 2990 PetscFunctionReturn(0); 2991 } 2992 2993 #undef __FUNCT__ 2994 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 2995 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 2996 { 2997 PetscSection section; 2998 PetscErrorCode ierr; 2999 3000 PetscFunctionBegin; 3001 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3002 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3003 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 3004 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3005 PetscFunctionReturn(0); 3006 } 3007 3008 #undef __FUNCT__ 3009 #define __FUNCT__ "DMPlexGetConeSection" 3010 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3011 { 3012 DM_Plex *mesh = (DM_Plex*) dm->data; 3013 3014 PetscFunctionBegin; 3015 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3016 if (section) *section = mesh->coneSection; 3017 PetscFunctionReturn(0); 3018 } 3019 3020 #undef __FUNCT__ 3021 #define __FUNCT__ "DMPlexGetSupportSection" 3022 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3023 { 3024 DM_Plex *mesh = (DM_Plex*) dm->data; 3025 3026 PetscFunctionBegin; 3027 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3028 if (section) *section = mesh->supportSection; 3029 PetscFunctionReturn(0); 3030 } 3031 3032 #undef __FUNCT__ 3033 #define __FUNCT__ "DMPlexGetCones" 3034 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3035 { 3036 DM_Plex *mesh = (DM_Plex*) dm->data; 3037 3038 PetscFunctionBegin; 3039 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3040 if (cones) *cones = mesh->cones; 3041 PetscFunctionReturn(0); 3042 } 3043 3044 #undef __FUNCT__ 3045 #define __FUNCT__ "DMPlexGetConeOrientations" 3046 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3047 { 3048 DM_Plex *mesh = (DM_Plex*) dm->data; 3049 3050 PetscFunctionBegin; 3051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3052 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3053 PetscFunctionReturn(0); 3054 } 3055 3056 /******************************** FEM Support **********************************/ 3057 3058 #undef __FUNCT__ 3059 #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static" 3060 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3061 { 3062 PetscScalar *array, *vArray; 3063 const PetscInt *cone, *coneO; 3064 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3065 PetscErrorCode ierr; 3066 3067 PetscFunctionBeginHot; 3068 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3069 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3070 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3071 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3072 if (!values || !*values) { 3073 if ((point >= pStart) && (point < pEnd)) { 3074 PetscInt dof; 3075 3076 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3077 size += dof; 3078 } 3079 for (p = 0; p < numPoints; ++p) { 3080 const PetscInt cp = cone[p]; 3081 PetscInt dof; 3082 3083 if ((cp < pStart) || (cp >= pEnd)) continue; 3084 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3085 size += dof; 3086 } 3087 if (!values) { 3088 if (csize) *csize = size; 3089 PetscFunctionReturn(0); 3090 } 3091 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 3092 } else { 3093 array = *values; 3094 } 3095 size = 0; 3096 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3097 if ((point >= pStart) && (point < pEnd)) { 3098 PetscInt dof, off, d; 3099 PetscScalar *varr; 3100 3101 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3102 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3103 varr = &vArray[off]; 3104 for (d = 0; d < dof; ++d, ++offset) { 3105 array[offset] = varr[d]; 3106 } 3107 size += dof; 3108 } 3109 for (p = 0; p < numPoints; ++p) { 3110 const PetscInt cp = cone[p]; 3111 PetscInt o = coneO[p]; 3112 PetscInt dof, off, d; 3113 PetscScalar *varr; 3114 3115 if ((cp < pStart) || (cp >= pEnd)) continue; 3116 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3117 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3118 varr = &vArray[off]; 3119 if (o >= 0) { 3120 for (d = 0; d < dof; ++d, ++offset) { 3121 array[offset] = varr[d]; 3122 } 3123 } else { 3124 for (d = dof-1; d >= 0; --d, ++offset) { 3125 array[offset] = varr[d]; 3126 } 3127 } 3128 size += dof; 3129 } 3130 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3131 if (!*values) { 3132 if (csize) *csize = size; 3133 *values = array; 3134 } else { 3135 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3136 *csize = size; 3137 } 3138 PetscFunctionReturn(0); 3139 } 3140 3141 #undef __FUNCT__ 3142 #define __FUNCT__ "DMPlexVecGetClosure_Static" 3143 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3144 { 3145 PetscInt offset = 0, p; 3146 PetscErrorCode ierr; 3147 3148 PetscFunctionBeginHot; 3149 *size = 0; 3150 for (p = 0; p < numPoints*2; p += 2) { 3151 const PetscInt point = points[p]; 3152 const PetscInt o = points[p+1]; 3153 PetscInt dof, off, d; 3154 const PetscScalar *varr; 3155 3156 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3157 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3158 varr = &vArray[off]; 3159 if (o >= 0) { 3160 for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 3161 } else { 3162 for (d = dof-1; d >= 0; --d, ++offset) array[offset] = varr[d]; 3163 } 3164 } 3165 *size = offset; 3166 PetscFunctionReturn(0); 3167 } 3168 3169 #undef __FUNCT__ 3170 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 3171 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3172 { 3173 PetscInt offset = 0, f; 3174 PetscErrorCode ierr; 3175 3176 PetscFunctionBeginHot; 3177 *size = 0; 3178 for (f = 0; f < numFields; ++f) { 3179 PetscInt fcomp, p; 3180 3181 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3182 for (p = 0; p < numPoints*2; p += 2) { 3183 const PetscInt point = points[p]; 3184 const PetscInt o = points[p+1]; 3185 PetscInt fdof, foff, d, c; 3186 const PetscScalar *varr; 3187 3188 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3189 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3190 varr = &vArray[foff]; 3191 if (o >= 0) { 3192 for (d = 0; d < fdof; ++d, ++offset) array[offset] = varr[d]; 3193 } else { 3194 for (d = fdof/fcomp-1; d >= 0; --d) { 3195 for (c = 0; c < fcomp; ++c, ++offset) { 3196 array[offset] = varr[d*fcomp+c]; 3197 } 3198 } 3199 } 3200 } 3201 } 3202 *size = offset; 3203 PetscFunctionReturn(0); 3204 } 3205 3206 #undef __FUNCT__ 3207 #define __FUNCT__ "DMPlexVecGetClosure" 3208 /*@C 3209 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 3210 3211 Not collective 3212 3213 Input Parameters: 3214 + dm - The DM 3215 . section - The section describing the layout in v, or NULL to use the default section 3216 . v - The local vector 3217 - point - The sieve point in the DM 3218 3219 Output Parameters: 3220 + csize - The number of values in the closure, or NULL 3221 - values - The array of values, which is a borrowed array and should not be freed 3222 3223 Fortran Notes: 3224 Since it returns an array, this routine is only available in Fortran 90, and you must 3225 include petsc.h90 in your code. 3226 3227 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3228 3229 Level: intermediate 3230 3231 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3232 @*/ 3233 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3234 { 3235 PetscSection clSection; 3236 IS clPoints; 3237 PetscScalar *array, *vArray; 3238 PetscInt *points = NULL; 3239 const PetscInt *clp; 3240 PetscInt depth, numFields, numPoints, size; 3241 PetscErrorCode ierr; 3242 3243 PetscFunctionBeginHot; 3244 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3245 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3246 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3247 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3248 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3249 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3250 if (depth == 1 && numFields < 2) { 3251 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 3252 PetscFunctionReturn(0); 3253 } 3254 /* Get points */ 3255 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3256 if (!clPoints) { 3257 PetscInt pStart, pEnd, p, q; 3258 3259 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3260 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3261 /* Compress out points not in the section */ 3262 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3263 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3264 points[q*2] = points[p]; 3265 points[q*2+1] = points[p+1]; 3266 ++q; 3267 } 3268 } 3269 numPoints = q; 3270 } else { 3271 PetscInt dof, off; 3272 3273 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3274 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3275 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3276 numPoints = dof/2; 3277 points = (PetscInt *) &clp[off]; 3278 } 3279 /* Get array */ 3280 if (!values || !*values) { 3281 PetscInt asize = 0, dof, p; 3282 3283 for (p = 0; p < numPoints*2; p += 2) { 3284 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3285 asize += dof; 3286 } 3287 if (!values) { 3288 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3289 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3290 if (csize) *csize = asize; 3291 PetscFunctionReturn(0); 3292 } 3293 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 3294 } else { 3295 array = *values; 3296 } 3297 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3298 /* Get values */ 3299 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, vArray, &size, array);CHKERRQ(ierr);} 3300 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, vArray, &size, array);CHKERRQ(ierr);} 3301 /* Cleanup points */ 3302 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3303 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3304 /* Cleanup array */ 3305 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3306 if (!*values) { 3307 if (csize) *csize = size; 3308 *values = array; 3309 } else { 3310 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3311 *csize = size; 3312 } 3313 PetscFunctionReturn(0); 3314 } 3315 3316 #undef __FUNCT__ 3317 #define __FUNCT__ "DMPlexVecRestoreClosure" 3318 /*@C 3319 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 3320 3321 Not collective 3322 3323 Input Parameters: 3324 + dm - The DM 3325 . section - The section describing the layout in v, or NULL to use the default section 3326 . v - The local vector 3327 . point - The sieve point in the DM 3328 . csize - The number of values in the closure, or NULL 3329 - values - The array of values, which is a borrowed array and should not be freed 3330 3331 Fortran Notes: 3332 Since it returns an array, this routine is only available in Fortran 90, and you must 3333 include petsc.h90 in your code. 3334 3335 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3336 3337 Level: intermediate 3338 3339 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3340 @*/ 3341 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3342 { 3343 PetscInt size = 0; 3344 PetscErrorCode ierr; 3345 3346 PetscFunctionBegin; 3347 /* Should work without recalculating size */ 3348 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 3349 PetscFunctionReturn(0); 3350 } 3351 3352 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 3353 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 3354 3355 #undef __FUNCT__ 3356 #define __FUNCT__ "updatePoint_private" 3357 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[]) 3358 { 3359 PetscInt cdof; /* The number of constraints on this point */ 3360 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3361 PetscScalar *a; 3362 PetscInt off, cind = 0, k; 3363 PetscErrorCode ierr; 3364 3365 PetscFunctionBegin; 3366 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3367 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3368 a = &array[off]; 3369 if (!cdof || setBC) { 3370 if (orientation >= 0) { 3371 for (k = 0; k < dof; ++k) { 3372 fuse(&a[k], values[k]); 3373 } 3374 } else { 3375 for (k = 0; k < dof; ++k) { 3376 fuse(&a[k], values[dof-k-1]); 3377 } 3378 } 3379 } else { 3380 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3381 if (orientation >= 0) { 3382 for (k = 0; k < dof; ++k) { 3383 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3384 fuse(&a[k], values[k]); 3385 } 3386 } else { 3387 for (k = 0; k < dof; ++k) { 3388 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3389 fuse(&a[k], values[dof-k-1]); 3390 } 3391 } 3392 } 3393 PetscFunctionReturn(0); 3394 } 3395 3396 #undef __FUNCT__ 3397 #define __FUNCT__ "updatePointBC_private" 3398 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 3399 { 3400 PetscInt cdof; /* The number of constraints on this point */ 3401 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3402 PetscScalar *a; 3403 PetscInt off, cind = 0, k; 3404 PetscErrorCode ierr; 3405 3406 PetscFunctionBegin; 3407 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3408 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3409 a = &array[off]; 3410 if (cdof) { 3411 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3412 if (orientation >= 0) { 3413 for (k = 0; k < dof; ++k) { 3414 if ((cind < cdof) && (k == cdofs[cind])) { 3415 fuse(&a[k], values[k]); 3416 ++cind; 3417 } 3418 } 3419 } else { 3420 for (k = 0; k < dof; ++k) { 3421 if ((cind < cdof) && (k == cdofs[cind])) { 3422 fuse(&a[k], values[dof-k-1]); 3423 ++cind; 3424 } 3425 } 3426 } 3427 } 3428 PetscFunctionReturn(0); 3429 } 3430 3431 #undef __FUNCT__ 3432 #define __FUNCT__ "updatePointFields_private" 3433 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[]) 3434 { 3435 PetscScalar *a; 3436 PetscInt fdof, foff, fcdof, foffset = *offset; 3437 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3438 PetscInt cind = 0, k, c; 3439 PetscErrorCode ierr; 3440 3441 PetscFunctionBegin; 3442 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3443 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3444 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3445 a = &array[foff]; 3446 if (!fcdof || setBC) { 3447 if (o >= 0) { 3448 for (k = 0; k < fdof; ++k) fuse(&a[k], values[foffset+k]); 3449 } else { 3450 for (k = fdof/fcomp-1; k >= 0; --k) { 3451 for (c = 0; c < fcomp; ++c) { 3452 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3453 } 3454 } 3455 } 3456 } else { 3457 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3458 if (o >= 0) { 3459 for (k = 0; k < fdof; ++k) { 3460 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 3461 fuse(&a[k], values[foffset+k]); 3462 } 3463 } else { 3464 for (k = fdof/fcomp-1; k >= 0; --k) { 3465 for (c = 0; c < fcomp; ++c) { 3466 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 3467 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3468 } 3469 } 3470 } 3471 } 3472 *offset += fdof; 3473 PetscFunctionReturn(0); 3474 } 3475 3476 #undef __FUNCT__ 3477 #define __FUNCT__ "updatePointFieldsBC_private" 3478 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[]) 3479 { 3480 PetscScalar *a; 3481 PetscInt fdof, foff, fcdof, foffset = *offset; 3482 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3483 PetscInt cind = 0, k, c; 3484 PetscErrorCode ierr; 3485 3486 PetscFunctionBegin; 3487 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3488 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3489 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3490 a = &array[foff]; 3491 if (fcdof) { 3492 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3493 if (o >= 0) { 3494 for (k = 0; k < fdof; ++k) { 3495 if ((cind < fcdof) && (k == fcdofs[cind])) { 3496 fuse(&a[k], values[foffset+k]); 3497 ++cind; 3498 } 3499 } 3500 } else { 3501 for (k = fdof/fcomp-1; k >= 0; --k) { 3502 for (c = 0; c < fcomp; ++c) { 3503 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 3504 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3505 ++cind; 3506 } 3507 } 3508 } 3509 } 3510 } 3511 *offset += fdof; 3512 PetscFunctionReturn(0); 3513 } 3514 3515 #undef __FUNCT__ 3516 #define __FUNCT__ "DMPlexVecSetClosure_Static" 3517 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3518 { 3519 PetscScalar *array; 3520 const PetscInt *cone, *coneO; 3521 PetscInt pStart, pEnd, p, numPoints, off, dof; 3522 PetscErrorCode ierr; 3523 3524 PetscFunctionBeginHot; 3525 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3526 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3527 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3528 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3529 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3530 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 3531 const PetscInt cp = !p ? point : cone[p-1]; 3532 const PetscInt o = !p ? 0 : coneO[p-1]; 3533 3534 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 3535 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3536 /* ADD_VALUES */ 3537 { 3538 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3539 PetscScalar *a; 3540 PetscInt cdof, coff, cind = 0, k; 3541 3542 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 3543 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 3544 a = &array[coff]; 3545 if (!cdof) { 3546 if (o >= 0) { 3547 for (k = 0; k < dof; ++k) { 3548 a[k] += values[off+k]; 3549 } 3550 } else { 3551 for (k = 0; k < dof; ++k) { 3552 a[k] += values[off+dof-k-1]; 3553 } 3554 } 3555 } else { 3556 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 3557 if (o >= 0) { 3558 for (k = 0; k < dof; ++k) { 3559 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3560 a[k] += values[off+k]; 3561 } 3562 } else { 3563 for (k = 0; k < dof; ++k) { 3564 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3565 a[k] += values[off+dof-k-1]; 3566 } 3567 } 3568 } 3569 } 3570 } 3571 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3572 PetscFunctionReturn(0); 3573 } 3574 3575 #undef __FUNCT__ 3576 #define __FUNCT__ "DMPlexVecSetClosure" 3577 /*@C 3578 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 3579 3580 Not collective 3581 3582 Input Parameters: 3583 + dm - The DM 3584 . section - The section describing the layout in v, or NULL to use the default section 3585 . v - The local vector 3586 . point - The sieve point in the DM 3587 . values - The array of values 3588 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 3589 3590 Fortran Notes: 3591 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3592 3593 Level: intermediate 3594 3595 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 3596 @*/ 3597 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3598 { 3599 PetscSection clSection; 3600 IS clPoints; 3601 PetscScalar *array; 3602 PetscInt *points = NULL; 3603 const PetscInt *clp; 3604 PetscInt depth, numFields, numPoints, p; 3605 PetscErrorCode ierr; 3606 3607 PetscFunctionBeginHot; 3608 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3609 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3610 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3611 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3612 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3613 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3614 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 3615 ierr = DMPlexVecSetClosure_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 3616 PetscFunctionReturn(0); 3617 } 3618 /* Get points */ 3619 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3620 if (!clPoints) { 3621 PetscInt pStart, pEnd, q; 3622 3623 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3624 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3625 /* Compress out points not in the section */ 3626 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3627 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3628 points[q*2] = points[p]; 3629 points[q*2+1] = points[p+1]; 3630 ++q; 3631 } 3632 } 3633 numPoints = q; 3634 } else { 3635 PetscInt dof, off; 3636 3637 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3638 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3639 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3640 numPoints = dof/2; 3641 points = (PetscInt *) &clp[off]; 3642 } 3643 /* Get array */ 3644 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3645 /* Get values */ 3646 if (numFields > 0) { 3647 PetscInt offset = 0, fcomp, f; 3648 for (f = 0; f < numFields; ++f) { 3649 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3650 switch (mode) { 3651 case INSERT_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, insert, PETSC_FALSE, values, &offset, array); 3656 } break; 3657 case INSERT_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, insert, PETSC_TRUE, values, &offset, array); 3662 } break; 3663 case INSERT_BC_VALUES: 3664 for (p = 0; p < numPoints*2; p += 2) { 3665 const PetscInt point = points[p]; 3666 const PetscInt o = points[p+1]; 3667 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3668 } break; 3669 case ADD_VALUES: 3670 for (p = 0; p < numPoints*2; p += 2) { 3671 const PetscInt point = points[p]; 3672 const PetscInt o = points[p+1]; 3673 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3674 } break; 3675 case ADD_ALL_VALUES: 3676 for (p = 0; p < numPoints*2; p += 2) { 3677 const PetscInt point = points[p]; 3678 const PetscInt o = points[p+1]; 3679 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3680 } break; 3681 default: 3682 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 3683 } 3684 } 3685 } else { 3686 PetscInt dof, off; 3687 3688 switch (mode) { 3689 case INSERT_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, insert, PETSC_FALSE, o, &values[off], array); 3694 } break; 3695 case INSERT_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, insert, PETSC_TRUE, o, &values[off], array); 3700 } break; 3701 case INSERT_BC_VALUES: 3702 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3703 PetscInt o = points[p+1]; 3704 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3705 updatePointBC_private(section, points[p], dof, insert, o, &values[off], array); 3706 } break; 3707 case ADD_VALUES: 3708 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3709 PetscInt o = points[p+1]; 3710 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3711 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 3712 } break; 3713 case ADD_ALL_VALUES: 3714 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3715 PetscInt o = points[p+1]; 3716 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3717 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 3718 } break; 3719 default: 3720 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 3721 } 3722 } 3723 /* Cleanup points */ 3724 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3725 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3726 /* Cleanup array */ 3727 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3728 PetscFunctionReturn(0); 3729 } 3730 3731 #undef __FUNCT__ 3732 #define __FUNCT__ "DMPlexVecSetFieldClosure_Internal" 3733 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, const PetscScalar values[], InsertMode mode) 3734 { 3735 PetscSection clSection; 3736 IS clPoints; 3737 PetscScalar *array; 3738 PetscInt *points = NULL; 3739 const PetscInt *clp; 3740 PetscInt numFields, numPoints, p; 3741 PetscInt offset = 0, fcomp, f; 3742 PetscErrorCode ierr; 3743 3744 PetscFunctionBeginHot; 3745 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3746 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3747 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3748 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3749 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3750 /* Get points */ 3751 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3752 if (!clPoints) { 3753 PetscInt pStart, pEnd, q; 3754 3755 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3756 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3757 /* Compress out points not in the section */ 3758 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3759 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3760 points[q*2] = points[p]; 3761 points[q*2+1] = points[p+1]; 3762 ++q; 3763 } 3764 } 3765 numPoints = q; 3766 } else { 3767 PetscInt dof, off; 3768 3769 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3770 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3771 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3772 numPoints = dof/2; 3773 points = (PetscInt *) &clp[off]; 3774 } 3775 /* Get array */ 3776 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3777 /* Get values */ 3778 for (f = 0; f < numFields; ++f) { 3779 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3780 if (!fieldActive[f]) { 3781 for (p = 0; p < numPoints*2; p += 2) { 3782 PetscInt fdof; 3783 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 3784 offset += fdof; 3785 } 3786 continue; 3787 } 3788 switch (mode) { 3789 case INSERT_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, insert, PETSC_FALSE, values, &offset, array); 3794 } break; 3795 case INSERT_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, insert, PETSC_TRUE, values, &offset, array); 3800 } break; 3801 case INSERT_BC_VALUES: 3802 for (p = 0; p < numPoints*2; p += 2) { 3803 const PetscInt point = points[p]; 3804 const PetscInt o = points[p+1]; 3805 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3806 } break; 3807 case ADD_VALUES: 3808 for (p = 0; p < numPoints*2; p += 2) { 3809 const PetscInt point = points[p]; 3810 const PetscInt o = points[p+1]; 3811 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3812 } break; 3813 case ADD_ALL_VALUES: 3814 for (p = 0; p < numPoints*2; p += 2) { 3815 const PetscInt point = points[p]; 3816 const PetscInt o = points[p+1]; 3817 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3818 } break; 3819 default: 3820 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 3821 } 3822 } 3823 /* Cleanup points */ 3824 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3825 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3826 /* Cleanup array */ 3827 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3828 PetscFunctionReturn(0); 3829 } 3830 3831 #undef __FUNCT__ 3832 #define __FUNCT__ "DMPlexPrintMatSetValues" 3833 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 3834 { 3835 PetscMPIInt rank; 3836 PetscInt i, j; 3837 PetscErrorCode ierr; 3838 3839 PetscFunctionBegin; 3840 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 3841 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 3842 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 3843 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 3844 numCIndices = numCIndices ? numCIndices : numRIndices; 3845 for (i = 0; i < numRIndices; i++) { 3846 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 3847 for (j = 0; j < numCIndices; j++) { 3848 #if defined(PETSC_USE_COMPLEX) 3849 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 3850 #else 3851 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 3852 #endif 3853 } 3854 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 3855 } 3856 PetscFunctionReturn(0); 3857 } 3858 3859 #undef __FUNCT__ 3860 #define __FUNCT__ "indicesPoint_private" 3861 /* . off - The global offset of this point */ 3862 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 3863 { 3864 PetscInt dof; /* The number of unknowns on this point */ 3865 PetscInt cdof; /* The number of constraints on this point */ 3866 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3867 PetscInt cind = 0, k; 3868 PetscErrorCode ierr; 3869 3870 PetscFunctionBegin; 3871 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3872 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3873 if (!cdof || setBC) { 3874 if (orientation >= 0) { 3875 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 3876 } else { 3877 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 3878 } 3879 } else { 3880 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3881 if (orientation >= 0) { 3882 for (k = 0; k < dof; ++k) { 3883 if ((cind < cdof) && (k == cdofs[cind])) { 3884 /* Insert check for returning constrained indices */ 3885 indices[*loff+k] = -(off+k+1); 3886 ++cind; 3887 } else { 3888 indices[*loff+k] = off+k-cind; 3889 } 3890 } 3891 } else { 3892 for (k = 0; k < dof; ++k) { 3893 if ((cind < cdof) && (k == cdofs[cind])) { 3894 /* Insert check for returning constrained indices */ 3895 indices[*loff+dof-k-1] = -(off+k+1); 3896 ++cind; 3897 } else { 3898 indices[*loff+dof-k-1] = off+k-cind; 3899 } 3900 } 3901 } 3902 } 3903 *loff += dof; 3904 PetscFunctionReturn(0); 3905 } 3906 3907 #undef __FUNCT__ 3908 #define __FUNCT__ "indicesPointFields_private" 3909 /* . off - The global offset of this point */ 3910 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 3911 { 3912 PetscInt numFields, foff, f; 3913 PetscErrorCode ierr; 3914 3915 PetscFunctionBegin; 3916 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3917 for (f = 0, foff = 0; f < numFields; ++f) { 3918 PetscInt fdof, fcomp, cfdof; 3919 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3920 PetscInt cind = 0, k, c; 3921 3922 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3923 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3924 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 3925 if (!cfdof || setBC) { 3926 if (orientation >= 0) { 3927 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 3928 } else { 3929 for (k = fdof/fcomp-1; k >= 0; --k) { 3930 for (c = 0; c < fcomp; ++c) { 3931 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 3932 } 3933 } 3934 } 3935 } else { 3936 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3937 if (orientation >= 0) { 3938 for (k = 0; k < fdof; ++k) { 3939 if ((cind < cfdof) && (k == fcdofs[cind])) { 3940 indices[foffs[f]+k] = -(off+foff+k+1); 3941 ++cind; 3942 } else { 3943 indices[foffs[f]+k] = off+foff+k-cind; 3944 } 3945 } 3946 } else { 3947 for (k = fdof/fcomp-1; k >= 0; --k) { 3948 for (c = 0; c < fcomp; ++c) { 3949 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 3950 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 3951 ++cind; 3952 } else { 3953 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 3954 } 3955 } 3956 } 3957 } 3958 } 3959 foff += fdof - cfdof; 3960 foffs[f] += fdof; 3961 } 3962 PetscFunctionReturn(0); 3963 } 3964 3965 #undef __FUNCT__ 3966 #define __FUNCT__ "DMPlexAnchorsModifyMat" 3967 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[]) 3968 { 3969 Mat cMat; 3970 PetscSection aSec, cSec; 3971 IS aIS; 3972 PetscInt aStart = -1, aEnd = -1; 3973 const PetscInt *anchors; 3974 PetscInt numFields, f, p, q, newP = 0; 3975 PetscInt newNumPoints = 0, newNumIndices = 0; 3976 PetscInt *newPoints, *indices, *newIndices; 3977 PetscInt maxAnchor, maxDof; 3978 PetscInt newOffsets[32]; 3979 PetscInt *pointMatOffsets[32]; 3980 PetscInt *newPointOffsets[32]; 3981 PetscScalar *pointMat[32]; 3982 PetscScalar *newValues,*tmpValues; 3983 PetscBool anyConstrained = PETSC_FALSE; 3984 PetscErrorCode ierr; 3985 3986 PetscFunctionBegin; 3987 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3988 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3989 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3990 3991 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 3992 /* if there are point-to-point constraints */ 3993 if (aSec) { 3994 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 3995 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 3996 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 3997 /* figure out how many points are going to be in the new element matrix 3998 * (we allow double counting, because it's all just going to be summed 3999 * into the global matrix anyway) */ 4000 for (p = 0; p < 2*numPoints; p+=2) { 4001 PetscInt b = points[p]; 4002 PetscInt bDof = 0; 4003 4004 if (b >= aStart && b < aEnd) { 4005 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4006 } 4007 if (bDof) { 4008 /* this point is constrained */ 4009 /* it is going to be replaced by its anchors */ 4010 PetscInt bOff, q; 4011 4012 anyConstrained = PETSC_TRUE; 4013 newNumPoints += bDof; 4014 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4015 for (q = 0; q < bDof; q++) { 4016 PetscInt a = anchors[bOff + q]; 4017 PetscInt aDof; 4018 4019 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4020 newNumIndices += aDof; 4021 for (f = 0; f < numFields; ++f) { 4022 PetscInt fDof; 4023 4024 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4025 newOffsets[f+1] += fDof; 4026 } 4027 } 4028 } 4029 else { 4030 /* this point is not constrained */ 4031 newNumPoints++; 4032 ierr = PetscSectionGetDof(section,b,&bDof);CHKERRQ(ierr); 4033 newNumIndices += bDof; 4034 for (f = 0; f < numFields; ++f) { 4035 PetscInt fDof; 4036 4037 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4038 newOffsets[f+1] += fDof; 4039 } 4040 } 4041 } 4042 } 4043 if (!anyConstrained) { 4044 *outNumPoints = 0; 4045 *outNumIndices = 0; 4046 *outPoints = NULL; 4047 *outValues = NULL; 4048 if (aSec) { 4049 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4050 } 4051 PetscFunctionReturn(0); 4052 } 4053 4054 for (f = 1; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4055 4056 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", newOffsets[numFields], newNumIndices); 4057 4058 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4059 4060 /* output arrays */ 4061 ierr = DMGetWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4062 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4063 4064 /* workspaces */ 4065 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4066 if (numFields) { 4067 for (f = 0; f < numFields; f++) { 4068 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4069 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4070 } 4071 } 4072 else { 4073 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4074 ierr = DMGetWorkArray(dm,numPoints,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4075 } 4076 4077 /* get workspaces for the point-to-point matrices */ 4078 if (numFields) { 4079 for (p = 0; p < numPoints; p++) { 4080 PetscInt b = points[2*p]; 4081 PetscInt bDof = 0; 4082 4083 if (b >= aStart && b < aEnd) { 4084 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4085 } 4086 if (bDof) { 4087 for (f = 0; f < numFields; f++) { 4088 PetscInt fDof, q, bOff, allFDof = 0; 4089 4090 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4091 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4092 for (q = 0; q < bDof; q++) { 4093 PetscInt a = anchors[bOff + q]; 4094 PetscInt aFDof; 4095 4096 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4097 allFDof += aFDof; 4098 } 4099 newPointOffsets[f][p+1] = allFDof; 4100 pointMatOffsets[f][p+1] = fDof * allFDof; 4101 } 4102 } 4103 else { 4104 for (f = 0; f < numFields; f++) { 4105 PetscInt fDof; 4106 4107 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4108 newPointOffsets[f][p+1] = fDof; 4109 pointMatOffsets[f][p+1] = 0; 4110 } 4111 } 4112 } 4113 for (f = 0; f < numFields; f++) { 4114 newPointOffsets[f][0] = 0; 4115 pointMatOffsets[f][0] = 0; 4116 for (p = 0; p < numPoints; p++) { 4117 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 4118 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 4119 } 4120 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4121 } 4122 } 4123 else { 4124 for (p = 0; p < numPoints; p++) { 4125 PetscInt b = points[2*p]; 4126 PetscInt bDof = 0; 4127 4128 if (b >= aStart && b < aEnd) { 4129 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4130 } 4131 if (bDof) { 4132 PetscInt dof, bOff, q, allDof = 0; 4133 4134 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4135 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4136 for (q = 0; q < bDof; q++) { 4137 PetscInt a = anchors[bOff + q], aDof; 4138 4139 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 4140 allDof += aDof; 4141 } 4142 newPointOffsets[0][p+1] = allDof; 4143 pointMatOffsets[0][p+1] = dof * allDof; 4144 } 4145 else { 4146 PetscInt dof; 4147 4148 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4149 newPointOffsets[0][p+1] = dof; 4150 pointMatOffsets[0][p+1] = 0; 4151 } 4152 } 4153 newPointOffsets[0][0] = 0; 4154 pointMatOffsets[0][0] = 0; 4155 for (p = 0; p < numPoints; p++) { 4156 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 4157 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 4158 } 4159 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4160 } 4161 4162 /* get the point-to-point matrices; construct newPoints */ 4163 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 4164 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4165 ierr = DMGetWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4166 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4167 if (numFields) { 4168 for (p = 0, newP = 0; p < numPoints; p++) { 4169 PetscInt b = points[2*p]; 4170 PetscInt o = points[2*p+1]; 4171 PetscInt bDof = 0; 4172 4173 if (b >= aStart && b < aEnd) { 4174 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4175 } 4176 if (bDof) { 4177 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 4178 4179 fStart[0] = 0; 4180 fEnd[0] = 0; 4181 for (f = 0; f < numFields; f++) { 4182 PetscInt fDof; 4183 4184 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 4185 fStart[f+1] = fStart[f] + fDof; 4186 fEnd[f+1] = fStart[f+1]; 4187 } 4188 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4189 ierr = indicesPointFields_private(cSec, b, bOff, fEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4190 4191 fAnchorStart[0] = 0; 4192 fAnchorEnd[0] = 0; 4193 for (f = 0; f < numFields; f++) { 4194 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 4195 4196 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 4197 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 4198 } 4199 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4200 for (q = 0; q < bDof; q++) { 4201 PetscInt a = anchors[bOff + q], aOff; 4202 4203 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4204 newPoints[2*(newP + q)] = a; 4205 newPoints[2*(newP + q) + 1] = 0; 4206 ierr = PetscSectionGetOffset(section, a, &aOff); 4207 ierr = indicesPointFields_private(section, a, aOff, fAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4208 } 4209 newP += bDof; 4210 4211 /* get the point-to-point submatrix */ 4212 for (f = 0; f < numFields; f++) { 4213 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 4214 } 4215 } 4216 else { 4217 newPoints[2 * newP] = b; 4218 newPoints[2 * newP + 1] = o; 4219 newP++; 4220 } 4221 } 4222 } else { 4223 for (p = 0; p < numPoints; p++) { 4224 PetscInt b = points[2*p]; 4225 PetscInt o = points[2*p+1]; 4226 PetscInt bDof = 0; 4227 4228 if (b >= aStart && b < aEnd) { 4229 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4230 } 4231 if (bDof) { 4232 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 4233 4234 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4235 ierr = indicesPoint_private(cSec, b, bOff, &bEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4236 4237 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4238 for (q = 0; q < bDof; q++) { 4239 PetscInt a = anchors[bOff + q], aOff; 4240 4241 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4242 4243 newPoints[2*(newP + q)] = a; 4244 newPoints[2*(newP + q) + 1] = 0; 4245 ierr = PetscSectionGetOffset(section, a, &aOff); 4246 ierr = indicesPoint_private(section, a, aOff, &bAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4247 } 4248 newP += bDof; 4249 4250 /* get the point-to-point submatrix */ 4251 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 4252 } 4253 else { 4254 newPoints[2 * newP] = b; 4255 newPoints[2 * newP + 1] = o; 4256 newP++; 4257 } 4258 } 4259 } 4260 4261 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 4262 /* multiply constraints on the right */ 4263 if (numFields) { 4264 for (f = 0; f < numFields; f++) { 4265 PetscInt oldOff = offsets[f]; 4266 4267 for (p = 0; p < numPoints; p++) { 4268 PetscInt cStart = newPointOffsets[f][p]; 4269 PetscInt b = points[2 * p]; 4270 PetscInt c, r, k; 4271 PetscInt dof; 4272 4273 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4274 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4275 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 4276 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 4277 4278 for (r = 0; r < numIndices; r++) { 4279 for (c = 0; c < nCols; c++) { 4280 for (k = 0; k < dof; k++) { 4281 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4282 } 4283 } 4284 } 4285 } 4286 else { 4287 /* copy this column as is */ 4288 for (r = 0; r < numIndices; r++) { 4289 for (c = 0; c < dof; c++) { 4290 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4291 } 4292 } 4293 } 4294 oldOff += dof; 4295 } 4296 } 4297 } 4298 else { 4299 PetscInt oldOff = 0; 4300 for (p = 0; p < numPoints; p++) { 4301 PetscInt cStart = newPointOffsets[0][p]; 4302 PetscInt b = points[2 * p]; 4303 PetscInt c, r, k; 4304 PetscInt dof; 4305 4306 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4307 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4308 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 4309 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 4310 4311 for (r = 0; r < numIndices; r++) { 4312 for (c = 0; c < nCols; c++) { 4313 for (k = 0; k < dof; k++) { 4314 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4315 } 4316 } 4317 } 4318 } 4319 else { 4320 /* copy this column as is */ 4321 for (r = 0; r < numIndices; r++) { 4322 for (c = 0; c < dof; c++) { 4323 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4324 } 4325 } 4326 } 4327 oldOff += dof; 4328 } 4329 } 4330 4331 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 4332 /* multiply constraints transpose on the left */ 4333 if (numFields) { 4334 for (f = 0; f < numFields; f++) { 4335 PetscInt oldOff = offsets[f]; 4336 4337 for (p = 0; p < numPoints; p++) { 4338 PetscInt rStart = newPointOffsets[f][p]; 4339 PetscInt b = points[2 * p]; 4340 PetscInt c, r, k; 4341 PetscInt dof; 4342 4343 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4344 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4345 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 4346 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 4347 4348 for (r = 0; r < nRows; r++) { 4349 for (c = 0; c < newNumIndices; c++) { 4350 for (k = 0; k < dof; k++) { 4351 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4352 } 4353 } 4354 } 4355 } 4356 else { 4357 /* copy this row as is */ 4358 for (r = 0; r < dof; r++) { 4359 for (c = 0; c < newNumIndices; c++) { 4360 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4361 } 4362 } 4363 } 4364 oldOff += dof; 4365 } 4366 } 4367 } 4368 else { 4369 PetscInt oldOff = 0; 4370 4371 for (p = 0; p < numPoints; p++) { 4372 PetscInt rStart = newPointOffsets[0][p]; 4373 PetscInt b = points[2 * p]; 4374 PetscInt c, r, k; 4375 PetscInt dof; 4376 4377 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4378 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4379 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 4380 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 4381 4382 for (r = 0; r < nRows; r++) { 4383 for (c = 0; c < newNumIndices; c++) { 4384 for (k = 0; k < dof; k++) { 4385 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4386 } 4387 } 4388 } 4389 } 4390 else { 4391 /* copy this row as is */ 4392 for (r = 0; r < dof; c++) { 4393 for (c = 0; c < newNumIndices; c++) { 4394 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4395 } 4396 } 4397 } 4398 oldOff += dof; 4399 } 4400 } 4401 4402 /* clean up */ 4403 ierr = DMRestoreWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4404 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4405 if (numFields) { 4406 for (f = 0; f < numFields; f++) { 4407 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4408 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4409 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4410 } 4411 } 4412 else { 4413 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4414 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4415 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4416 } 4417 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4418 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4419 4420 /* output */ 4421 *outNumPoints = newNumPoints; 4422 *outNumIndices = newNumIndices; 4423 *outPoints = newPoints; 4424 *outValues = newValues; 4425 for (f = 0; f < numFields; f++) { 4426 offsets[f] = newOffsets[f]; 4427 } 4428 PetscFunctionReturn(0); 4429 } 4430 4431 #undef __FUNCT__ 4432 #define __FUNCT__ "DMPlexMatSetClosure" 4433 /*@C 4434 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 4435 4436 Not collective 4437 4438 Input Parameters: 4439 + dm - The DM 4440 . section - The section describing the layout in v, or NULL to use the default section 4441 . globalSection - The section describing the layout in v, or NULL to use the default global section 4442 . A - The matrix 4443 . point - The sieve point in the DM 4444 . values - The array of values 4445 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4446 4447 Fortran Notes: 4448 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4449 4450 Level: intermediate 4451 4452 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 4453 @*/ 4454 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4455 { 4456 DM_Plex *mesh = (DM_Plex*) dm->data; 4457 PetscSection clSection; 4458 IS clPoints; 4459 PetscInt *points = NULL, *newPoints; 4460 const PetscInt *clp; 4461 PetscInt *indices; 4462 PetscInt offsets[32]; 4463 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 4464 PetscScalar *newValues; 4465 PetscErrorCode ierr; 4466 4467 PetscFunctionBegin; 4468 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4469 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4470 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4471 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 4472 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4473 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 4474 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4475 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4476 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4477 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4478 if (!clPoints) { 4479 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4480 /* Compress out points not in the section */ 4481 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4482 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4483 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4484 points[q*2] = points[p]; 4485 points[q*2+1] = points[p+1]; 4486 ++q; 4487 } 4488 } 4489 numPoints = q; 4490 } else { 4491 PetscInt dof, off; 4492 4493 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4494 numPoints = dof/2; 4495 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4496 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4497 points = (PetscInt *) &clp[off]; 4498 } 4499 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 4500 PetscInt fdof; 4501 4502 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4503 for (f = 0; f < numFields; ++f) { 4504 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4505 offsets[f+1] += fdof; 4506 } 4507 numIndices += dof; 4508 } 4509 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 4510 4511 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 4512 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets);CHKERRQ(ierr); 4513 if (newNumPoints) { 4514 if (!clPoints) { 4515 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4516 } else { 4517 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4518 } 4519 numPoints = newNumPoints; 4520 numIndices = newNumIndices; 4521 points = newPoints; 4522 values = newValues; 4523 } 4524 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4525 if (numFields) { 4526 for (p = 0; p < numPoints*2; p += 2) { 4527 PetscInt o = points[p+1]; 4528 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4529 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 4530 } 4531 } else { 4532 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4533 PetscInt o = points[p+1]; 4534 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4535 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 4536 } 4537 } 4538 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 4539 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 4540 if (ierr) { 4541 PetscMPIInt rank; 4542 PetscErrorCode ierr2; 4543 4544 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4545 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4546 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 4547 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 4548 CHKERRQ(ierr); 4549 } 4550 if (newNumPoints) { 4551 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4552 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4553 } 4554 else { 4555 if (!clPoints) { 4556 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4557 } else { 4558 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4559 } 4560 } 4561 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4562 PetscFunctionReturn(0); 4563 } 4564 4565 #undef __FUNCT__ 4566 #define __FUNCT__ "DMPlexMatSetClosureRefined" 4567 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4568 { 4569 DM_Plex *mesh = (DM_Plex*) dmf->data; 4570 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4571 PetscInt *cpoints = NULL; 4572 PetscInt *findices, *cindices; 4573 PetscInt foffsets[32], coffsets[32]; 4574 CellRefiner cellRefiner; 4575 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4576 PetscErrorCode ierr; 4577 4578 PetscFunctionBegin; 4579 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4580 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4581 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4582 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4583 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4584 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4585 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4586 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4587 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4588 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4589 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 4590 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4591 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4592 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4593 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4594 /* Column indices */ 4595 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4596 maxFPoints = numCPoints; 4597 /* Compress out points not in the section */ 4598 /* TODO: Squeeze out points with 0 dof as well */ 4599 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4600 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4601 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4602 cpoints[q*2] = cpoints[p]; 4603 cpoints[q*2+1] = cpoints[p+1]; 4604 ++q; 4605 } 4606 } 4607 numCPoints = q; 4608 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4609 PetscInt fdof; 4610 4611 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4612 if (!dof) continue; 4613 for (f = 0; f < numFields; ++f) { 4614 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4615 coffsets[f+1] += fdof; 4616 } 4617 numCIndices += dof; 4618 } 4619 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4620 /* Row indices */ 4621 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4622 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4623 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4624 for (r = 0, q = 0; r < numSubcells; ++r) { 4625 /* TODO Map from coarse to fine cells */ 4626 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4627 /* Compress out points not in the section */ 4628 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4629 for (p = 0; p < numFPoints*2; p += 2) { 4630 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4631 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4632 if (!dof) continue; 4633 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4634 if (s < q) continue; 4635 ftotpoints[q*2] = fpoints[p]; 4636 ftotpoints[q*2+1] = fpoints[p+1]; 4637 ++q; 4638 } 4639 } 4640 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4641 } 4642 numFPoints = q; 4643 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 4644 PetscInt fdof; 4645 4646 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 4647 if (!dof) continue; 4648 for (f = 0; f < numFields; ++f) { 4649 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 4650 foffsets[f+1] += fdof; 4651 } 4652 numFIndices += dof; 4653 } 4654 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 4655 4656 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 4657 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 4658 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 4659 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 4660 if (numFields) { 4661 for (p = 0; p < numFPoints*2; p += 2) { 4662 PetscInt o = ftotpoints[p+1]; 4663 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4664 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 4665 } 4666 for (p = 0; p < numCPoints*2; p += 2) { 4667 PetscInt o = cpoints[p+1]; 4668 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4669 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 4670 } 4671 } else { 4672 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 4673 PetscInt o = ftotpoints[p+1]; 4674 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4675 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 4676 } 4677 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 4678 PetscInt o = cpoints[p+1]; 4679 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4680 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 4681 } 4682 } 4683 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 4684 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 4685 if (ierr) { 4686 PetscMPIInt rank; 4687 PetscErrorCode ierr2; 4688 4689 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4690 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4691 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 4692 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 4693 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 4694 CHKERRQ(ierr); 4695 } 4696 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4697 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4698 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 4699 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 4700 PetscFunctionReturn(0); 4701 } 4702 4703 #undef __FUNCT__ 4704 #define __FUNCT__ "DMPlexMatGetClosureIndicesRefined" 4705 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 4706 { 4707 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4708 PetscInt *cpoints = NULL; 4709 PetscInt foffsets[32], coffsets[32]; 4710 CellRefiner cellRefiner; 4711 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4712 PetscErrorCode ierr; 4713 4714 PetscFunctionBegin; 4715 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4716 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4717 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4718 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4719 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4720 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4721 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4722 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4723 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4724 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4725 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4726 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4727 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4728 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4729 /* Column indices */ 4730 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4731 maxFPoints = numCPoints; 4732 /* Compress out points not in the section */ 4733 /* TODO: Squeeze out points with 0 dof as well */ 4734 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4735 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4736 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4737 cpoints[q*2] = cpoints[p]; 4738 cpoints[q*2+1] = cpoints[p+1]; 4739 ++q; 4740 } 4741 } 4742 numCPoints = q; 4743 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4744 PetscInt fdof; 4745 4746 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4747 if (!dof) continue; 4748 for (f = 0; f < numFields; ++f) { 4749 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4750 coffsets[f+1] += fdof; 4751 } 4752 numCIndices += dof; 4753 } 4754 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4755 /* Row indices */ 4756 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4757 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4758 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4759 for (r = 0, q = 0; r < numSubcells; ++r) { 4760 /* TODO Map from coarse to fine cells */ 4761 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4762 /* Compress out points not in the section */ 4763 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4764 for (p = 0; p < numFPoints*2; p += 2) { 4765 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4766 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4767 if (!dof) continue; 4768 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4769 if (s < q) continue; 4770 ftotpoints[q*2] = fpoints[p]; 4771 ftotpoints[q*2+1] = fpoints[p+1]; 4772 ++q; 4773 } 4774 } 4775 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4776 } 4777 numFPoints = q; 4778 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 4779 PetscInt fdof; 4780 4781 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 4782 if (!dof) continue; 4783 for (f = 0; f < numFields; ++f) { 4784 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 4785 foffsets[f+1] += fdof; 4786 } 4787 numFIndices += dof; 4788 } 4789 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 4790 4791 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 4792 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 4793 if (numFields) { 4794 for (p = 0; p < numFPoints*2; p += 2) { 4795 PetscInt o = ftotpoints[p+1]; 4796 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4797 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 4798 } 4799 for (p = 0; p < numCPoints*2; p += 2) { 4800 PetscInt o = cpoints[p+1]; 4801 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4802 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 4803 } 4804 } else { 4805 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 4806 PetscInt o = ftotpoints[p+1]; 4807 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4808 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 4809 } 4810 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 4811 PetscInt o = cpoints[p+1]; 4812 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4813 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 4814 } 4815 } 4816 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4817 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4818 PetscFunctionReturn(0); 4819 } 4820 4821 #undef __FUNCT__ 4822 #define __FUNCT__ "DMPlexGetHybridBounds" 4823 /*@ 4824 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 4825 4826 Input Parameter: 4827 . dm - The DMPlex object 4828 4829 Output Parameters: 4830 + cMax - The first hybrid cell 4831 . fMax - The first hybrid face 4832 . eMax - The first hybrid edge 4833 - vMax - The first hybrid vertex 4834 4835 Level: developer 4836 4837 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 4838 @*/ 4839 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 4840 { 4841 DM_Plex *mesh = (DM_Plex*) dm->data; 4842 PetscInt dim; 4843 PetscErrorCode ierr; 4844 4845 PetscFunctionBegin; 4846 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4847 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4848 if (cMax) *cMax = mesh->hybridPointMax[dim]; 4849 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 4850 if (eMax) *eMax = mesh->hybridPointMax[1]; 4851 if (vMax) *vMax = mesh->hybridPointMax[0]; 4852 PetscFunctionReturn(0); 4853 } 4854 4855 #undef __FUNCT__ 4856 #define __FUNCT__ "DMPlexSetHybridBounds" 4857 /*@ 4858 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 4859 4860 Input Parameters: 4861 . dm - The DMPlex object 4862 . cMax - The first hybrid cell 4863 . fMax - The first hybrid face 4864 . eMax - The first hybrid edge 4865 - vMax - The first hybrid vertex 4866 4867 Level: developer 4868 4869 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 4870 @*/ 4871 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 4872 { 4873 DM_Plex *mesh = (DM_Plex*) dm->data; 4874 PetscInt dim; 4875 PetscErrorCode ierr; 4876 4877 PetscFunctionBegin; 4878 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4879 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4880 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 4881 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 4882 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 4883 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 4884 PetscFunctionReturn(0); 4885 } 4886 4887 #undef __FUNCT__ 4888 #define __FUNCT__ "DMPlexGetVTKCellHeight" 4889 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 4890 { 4891 DM_Plex *mesh = (DM_Plex*) dm->data; 4892 4893 PetscFunctionBegin; 4894 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4895 PetscValidPointer(cellHeight, 2); 4896 *cellHeight = mesh->vtkCellHeight; 4897 PetscFunctionReturn(0); 4898 } 4899 4900 #undef __FUNCT__ 4901 #define __FUNCT__ "DMPlexSetVTKCellHeight" 4902 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 4903 { 4904 DM_Plex *mesh = (DM_Plex*) dm->data; 4905 4906 PetscFunctionBegin; 4907 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4908 mesh->vtkCellHeight = cellHeight; 4909 PetscFunctionReturn(0); 4910 } 4911 4912 #undef __FUNCT__ 4913 #define __FUNCT__ "DMPlexCreateNumbering_Private" 4914 /* We can easily have a form that takes an IS instead */ 4915 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 4916 { 4917 PetscSection section, globalSection; 4918 PetscInt *numbers, p; 4919 PetscErrorCode ierr; 4920 4921 PetscFunctionBegin; 4922 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4923 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 4924 for (p = pStart; p < pEnd; ++p) { 4925 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 4926 } 4927 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 4928 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 4929 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 4930 for (p = pStart; p < pEnd; ++p) { 4931 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 4932 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 4933 else numbers[p-pStart] += shift; 4934 } 4935 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 4936 if (globalSize) { 4937 PetscLayout layout; 4938 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 4939 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 4940 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4941 } 4942 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4943 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 4944 PetscFunctionReturn(0); 4945 } 4946 4947 #undef __FUNCT__ 4948 #define __FUNCT__ "DMPlexGetCellNumbering" 4949 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 4950 { 4951 DM_Plex *mesh = (DM_Plex*) dm->data; 4952 PetscInt cellHeight, cStart, cEnd, cMax; 4953 PetscErrorCode ierr; 4954 4955 PetscFunctionBegin; 4956 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4957 if (!mesh->globalCellNumbers) { 4958 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 4959 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 4960 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 4961 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 4962 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 4963 } 4964 *globalCellNumbers = mesh->globalCellNumbers; 4965 PetscFunctionReturn(0); 4966 } 4967 4968 #undef __FUNCT__ 4969 #define __FUNCT__ "DMPlexGetVertexNumbering" 4970 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 4971 { 4972 DM_Plex *mesh = (DM_Plex*) dm->data; 4973 PetscInt vStart, vEnd, vMax; 4974 PetscErrorCode ierr; 4975 4976 PetscFunctionBegin; 4977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4978 if (!mesh->globalVertexNumbers) { 4979 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4980 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 4981 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 4982 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 4983 } 4984 *globalVertexNumbers = mesh->globalVertexNumbers; 4985 PetscFunctionReturn(0); 4986 } 4987 4988 #undef __FUNCT__ 4989 #define __FUNCT__ "DMPlexCreatePointNumbering" 4990 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 4991 { 4992 IS nums[4]; 4993 PetscInt depths[4]; 4994 PetscInt depth, d, shift = 0; 4995 PetscErrorCode ierr; 4996 4997 PetscFunctionBegin; 4998 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4999 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5000 /* For unstratified meshes use dim instead of depth */ 5001 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 5002 depths[0] = depth; depths[1] = 0; 5003 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 5004 for (d = 0; d <= depth; ++d) { 5005 PetscInt pStart, pEnd, gsize; 5006 5007 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 5008 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 5009 shift += gsize; 5010 } 5011 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers); 5012 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 5013 PetscFunctionReturn(0); 5014 } 5015 5016 5017 #undef __FUNCT__ 5018 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 5019 /*@C 5020 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 5021 the local section and an SF describing the section point overlap. 5022 5023 Input Parameters: 5024 + s - The PetscSection for the local field layout 5025 . sf - The SF describing parallel layout of the section points 5026 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 5027 . label - The label specifying the points 5028 - labelValue - The label stratum specifying the points 5029 5030 Output Parameter: 5031 . gsection - The PetscSection for the global field layout 5032 5033 Note: This gives negative sizes and offsets to points not owned by this process 5034 5035 Level: developer 5036 5037 .seealso: PetscSectionCreate() 5038 @*/ 5039 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 5040 { 5041 PetscInt *neg = NULL, *tmpOff = NULL; 5042 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 5043 PetscErrorCode ierr; 5044 5045 PetscFunctionBegin; 5046 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr); 5047 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 5048 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 5049 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 5050 if (nroots >= 0) { 5051 if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart); 5052 ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr); 5053 if (nroots > pEnd-pStart) { 5054 ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr); 5055 } else { 5056 tmpOff = &(*gsection)->atlasDof[-pStart]; 5057 } 5058 } 5059 /* Mark ghost points with negative dof */ 5060 for (p = pStart; p < pEnd; ++p) { 5061 PetscInt value; 5062 5063 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 5064 if (value != labelValue) continue; 5065 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 5066 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 5067 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 5068 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 5069 if (neg) neg[p] = -(dof+1); 5070 } 5071 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 5072 if (nroots >= 0) { 5073 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5074 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5075 if (nroots > pEnd-pStart) { 5076 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} 5077 } 5078 } 5079 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 5080 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5081 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 5082 (*gsection)->atlasOff[p] = off; 5083 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 5084 } 5085 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr); 5086 globalOff -= off; 5087 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5088 (*gsection)->atlasOff[p] += globalOff; 5089 if (neg) neg[p] = -((*gsection)->atlasOff[p]+1); 5090 } 5091 /* Put in negative offsets for ghost points */ 5092 if (nroots >= 0) { 5093 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5094 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5095 if (nroots > pEnd-pStart) { 5096 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} 5097 } 5098 } 5099 if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);} 5100 ierr = PetscFree(neg);CHKERRQ(ierr); 5101 PetscFunctionReturn(0); 5102 } 5103 5104 #undef __FUNCT__ 5105 #define __FUNCT__ "DMPlexCheckSymmetry" 5106 /*@ 5107 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5108 5109 Input Parameters: 5110 + dm - The DMPlex object 5111 5112 Note: This is a useful diagnostic when creating meshes programmatically. 5113 5114 Level: developer 5115 5116 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5117 @*/ 5118 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5119 { 5120 PetscSection coneSection, supportSection; 5121 const PetscInt *cone, *support; 5122 PetscInt coneSize, c, supportSize, s; 5123 PetscInt pStart, pEnd, p, csize, ssize; 5124 PetscErrorCode ierr; 5125 5126 PetscFunctionBegin; 5127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5128 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5129 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5130 /* Check that point p is found in the support of its cone points, and vice versa */ 5131 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5132 for (p = pStart; p < pEnd; ++p) { 5133 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5134 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5135 for (c = 0; c < coneSize; ++c) { 5136 PetscBool dup = PETSC_FALSE; 5137 PetscInt d; 5138 for (d = c-1; d >= 0; --d) { 5139 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5140 } 5141 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5142 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5143 for (s = 0; s < supportSize; ++s) { 5144 if (support[s] == p) break; 5145 } 5146 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5147 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p); 5148 for (s = 0; s < coneSize; ++s) { 5149 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]); 5150 } 5151 ierr = PetscPrintf(PETSC_COMM_SELF, "\n"); 5152 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]); 5153 for (s = 0; s < supportSize; ++s) { 5154 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]); 5155 } 5156 ierr = PetscPrintf(PETSC_COMM_SELF, "\n"); 5157 if (dup) { 5158 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5159 } else { 5160 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5161 } 5162 } 5163 } 5164 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5165 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5166 for (s = 0; s < supportSize; ++s) { 5167 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5168 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5169 for (c = 0; c < coneSize; ++c) { 5170 if (cone[c] == p) break; 5171 } 5172 if (c >= coneSize) { 5173 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p); 5174 for (c = 0; c < supportSize; ++c) { 5175 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]); 5176 } 5177 ierr = PetscPrintf(PETSC_COMM_SELF, "\n"); 5178 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]); 5179 for (c = 0; c < coneSize; ++c) { 5180 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]); 5181 } 5182 ierr = PetscPrintf(PETSC_COMM_SELF, "\n"); 5183 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5184 } 5185 } 5186 } 5187 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5188 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5189 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5190 PetscFunctionReturn(0); 5191 } 5192 5193 #undef __FUNCT__ 5194 #define __FUNCT__ "DMPlexCheckSkeleton" 5195 /*@ 5196 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5197 5198 Input Parameters: 5199 + dm - The DMPlex object 5200 . isSimplex - Are the cells simplices or tensor products 5201 - cellHeight - Normally 0 5202 5203 Note: This is a useful diagnostic when creating meshes programmatically. 5204 5205 Level: developer 5206 5207 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5208 @*/ 5209 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5210 { 5211 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5212 PetscErrorCode ierr; 5213 5214 PetscFunctionBegin; 5215 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5216 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5217 switch (dim) { 5218 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5219 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5220 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5221 default: 5222 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5223 } 5224 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5225 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5226 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5227 cMax = cMax >= 0 ? cMax : cEnd; 5228 for (c = cStart; c < cMax; ++c) { 5229 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5230 5231 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5232 for (cl = 0; cl < closureSize*2; cl += 2) { 5233 const PetscInt p = closure[cl]; 5234 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5235 } 5236 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5237 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5238 } 5239 for (c = cMax; c < cEnd; ++c) { 5240 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5241 5242 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5243 for (cl = 0; cl < closureSize*2; cl += 2) { 5244 const PetscInt p = closure[cl]; 5245 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5246 } 5247 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5248 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5249 } 5250 PetscFunctionReturn(0); 5251 } 5252 5253 #undef __FUNCT__ 5254 #define __FUNCT__ "DMPlexCheckFaces" 5255 /*@ 5256 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5257 5258 Input Parameters: 5259 + dm - The DMPlex object 5260 . isSimplex - Are the cells simplices or tensor products 5261 - cellHeight - Normally 0 5262 5263 Note: This is a useful diagnostic when creating meshes programmatically. 5264 5265 Level: developer 5266 5267 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5268 @*/ 5269 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5270 { 5271 PetscInt pMax[4]; 5272 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5273 PetscErrorCode ierr; 5274 5275 PetscFunctionBegin; 5276 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5277 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5278 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5279 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5280 for (h = cellHeight; h < dim; ++h) { 5281 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5282 for (c = cStart; c < cEnd; ++c) { 5283 const PetscInt *cone, *ornt, *faces; 5284 PetscInt numFaces, faceSize, coneSize,f; 5285 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5286 5287 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5288 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5289 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5290 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5291 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5292 for (cl = 0; cl < closureSize*2; cl += 2) { 5293 const PetscInt p = closure[cl]; 5294 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5295 } 5296 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5297 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5298 for (f = 0; f < numFaces; ++f) { 5299 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5300 5301 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5302 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5303 const PetscInt p = fclosure[cl]; 5304 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5305 } 5306 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); 5307 for (v = 0; v < fnumCorners; ++v) { 5308 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]); 5309 } 5310 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5311 } 5312 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5313 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5314 } 5315 } 5316 PetscFunctionReturn(0); 5317 } 5318 5319 #undef __FUNCT__ 5320 #define __FUNCT__ "DMCreateInterpolation_Plex" 5321 /* Pointwise interpolation 5322 Just code FEM for now 5323 u^f = I u^c 5324 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5325 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5326 I_{ij} = psi^f_i phi^c_j 5327 */ 5328 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5329 { 5330 PetscSection gsc, gsf; 5331 PetscInt m, n; 5332 void *ctx; 5333 PetscErrorCode ierr; 5334 5335 PetscFunctionBegin; 5336 /* 5337 Loop over coarse cells 5338 Loop over coarse basis functions 5339 Loop over fine cells in coarse cell 5340 Loop over fine dual basis functions 5341 Evaluate coarse basis on fine dual basis quad points 5342 Sum 5343 Update local element matrix 5344 Accumulate to interpolation matrix 5345 5346 Can extend PetscFEIntegrateJacobian_Basic() to do a specialized cell loop 5347 */ 5348 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5349 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5350 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5351 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5352 /* We need to preallocate properly */ 5353 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5354 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5355 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5356 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5357 ierr = DMPlexComputeInterpolatorFEM(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr); 5358 /* Use naive scaling */ 5359 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5360 PetscFunctionReturn(0); 5361 } 5362 5363 #undef __FUNCT__ 5364 #define __FUNCT__ "DMCreateInjection_Plex" 5365 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, VecScatter *ctx) 5366 { 5367 PetscErrorCode ierr; 5368 5369 PetscFunctionBegin; 5370 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, ctx, NULL);CHKERRQ(ierr); 5371 PetscFunctionReturn(0); 5372 } 5373 5374 #undef __FUNCT__ 5375 #define __FUNCT__ "DMCreateDefaultSection_Plex" 5376 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 5377 { 5378 PetscSection section; 5379 IS *bcPoints; 5380 PetscBool *isFE; 5381 PetscInt *bcFields, *numComp, *numDof; 5382 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 5383 PetscInt cStart, cEnd, cEndInterior; 5384 PetscErrorCode ierr; 5385 5386 PetscFunctionBegin; 5387 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 5388 /* FE and FV boundary conditions are handled slightly differently */ 5389 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 5390 for (f = 0; f < numFields; ++f) { 5391 PetscObject obj; 5392 PetscClassId id; 5393 5394 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5395 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 5396 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 5397 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 5398 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 5399 } 5400 /* Allocate boundary point storage for FEM boundaries */ 5401 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5402 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5403 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5404 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 5405 ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 5406 for (bd = 0; bd < numBd; ++bd) { 5407 PetscInt field; 5408 PetscBool isEssential; 5409 5410 ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, NULL, &field, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5411 if (isFE[field] && isEssential) ++numBC; 5412 } 5413 /* Add ghost cell boundaries for FVM */ 5414 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 5415 ierr = PetscMalloc2(numBC,&bcFields,numBC,&bcPoints);CHKERRQ(ierr); 5416 /* Constrain ghost cells for FV */ 5417 for (f = 0; f < numFields; ++f) { 5418 PetscInt *newidx, c; 5419 5420 if (isFE[f] || cEndInterior < 0) continue; 5421 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 5422 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 5423 bcFields[bc] = f; 5424 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5425 } 5426 /* Handle FEM Dirichlet boundaries */ 5427 for (bd = 0; bd < numBd; ++bd) { 5428 const char *bdLabel; 5429 DMLabel label; 5430 const PetscInt *values; 5431 PetscInt bd2, field, numValues; 5432 PetscBool isEssential, duplicate = PETSC_FALSE; 5433 5434 ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 5435 if (!isFE[field]) continue; 5436 ierr = DMPlexGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 5437 /* Only want to modify label once */ 5438 for (bd2 = 0; bd2 < bd; ++bd2) { 5439 const char *bdname; 5440 ierr = DMPlexGetBoundary(dm, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5441 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 5442 if (duplicate) break; 5443 } 5444 if (!duplicate && (isFE[field])) { 5445 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 5446 ierr = DMPlexLabelAddCells(dm, label);CHKERRQ(ierr); 5447 } 5448 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 5449 if (isEssential) { 5450 PetscInt *newidx; 5451 PetscInt n, newn = 0, p, v; 5452 5453 bcFields[bc] = field; 5454 for (v = 0; v < numValues; ++v) { 5455 IS tmp; 5456 const PetscInt *idx; 5457 5458 ierr = DMPlexGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5459 if (!tmp) continue; 5460 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5461 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5462 if (isFE[field]) { 5463 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 5464 } else { 5465 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 5466 } 5467 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5468 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5469 } 5470 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 5471 newn = 0; 5472 for (v = 0; v < numValues; ++v) { 5473 IS tmp; 5474 const PetscInt *idx; 5475 5476 ierr = DMPlexGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5477 if (!tmp) continue; 5478 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5479 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5480 if (isFE[field]) { 5481 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 5482 } else { 5483 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 5484 } 5485 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5486 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5487 } 5488 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5489 } 5490 } 5491 /* Handle discretization */ 5492 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 5493 for (f = 0; f < numFields; ++f) { 5494 PetscObject obj; 5495 5496 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5497 if (isFE[f]) { 5498 PetscFE fe = (PetscFE) obj; 5499 const PetscInt *numFieldDof; 5500 PetscInt d; 5501 5502 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 5503 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 5504 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 5505 } else { 5506 PetscFV fv = (PetscFV) obj; 5507 5508 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 5509 numDof[f*(dim+1)+dim] = numComp[f]; 5510 } 5511 } 5512 for (f = 0; f < numFields; ++f) { 5513 PetscInt d; 5514 for (d = 1; d < dim; ++d) { 5515 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."); 5516 } 5517 } 5518 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcPoints, NULL, §ion);CHKERRQ(ierr); 5519 for (f = 0; f < numFields; ++f) { 5520 PetscFE fe; 5521 const char *name; 5522 5523 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 5524 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 5525 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 5526 } 5527 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 5528 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5529 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);} 5530 ierr = PetscFree2(bcFields,bcPoints);CHKERRQ(ierr); 5531 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 5532 ierr = PetscFree(isFE);CHKERRQ(ierr); 5533 PetscFunctionReturn(0); 5534 } 5535 5536 #undef __FUNCT__ 5537 #define __FUNCT__ "DMPlexGetCoarseDM" 5538 /*@ 5539 DMPlexGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5540 5541 Input Parameter: 5542 . dm - The DMPlex object 5543 5544 Output Parameter: 5545 . cdm - The coarse DM 5546 5547 Level: intermediate 5548 5549 .seealso: DMPlexSetCoarseDM() 5550 @*/ 5551 PetscErrorCode DMPlexGetCoarseDM(DM dm, DM *cdm) 5552 { 5553 PetscFunctionBegin; 5554 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5555 PetscValidPointer(cdm, 2); 5556 *cdm = ((DM_Plex *) dm->data)->coarseMesh; 5557 PetscFunctionReturn(0); 5558 } 5559 5560 #undef __FUNCT__ 5561 #define __FUNCT__ "DMPlexSetCoarseDM" 5562 /*@ 5563 DMPlexSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5564 5565 Input Parameters: 5566 + dm - The DMPlex object 5567 - cdm - The coarse DM 5568 5569 Level: intermediate 5570 5571 .seealso: DMPlexGetCoarseDM() 5572 @*/ 5573 PetscErrorCode DMPlexSetCoarseDM(DM dm, DM cdm) 5574 { 5575 DM_Plex *mesh; 5576 PetscErrorCode ierr; 5577 5578 PetscFunctionBegin; 5579 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5580 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5581 mesh = (DM_Plex *) dm->data; 5582 ierr = DMDestroy(&mesh->coarseMesh);CHKERRQ(ierr); 5583 mesh->coarseMesh = cdm; 5584 ierr = PetscObjectReference((PetscObject) mesh->coarseMesh);CHKERRQ(ierr); 5585 PetscFunctionReturn(0); 5586 } 5587 5588 /* anchors */ 5589 #undef __FUNCT__ 5590 #define __FUNCT__ "DMPlexGetAnchors" 5591 /*@ 5592 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 5593 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 5594 5595 not collective 5596 5597 Input Parameters: 5598 . dm - The DMPlex object 5599 5600 Output Parameters: 5601 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 5602 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 5603 5604 5605 Level: intermediate 5606 5607 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 5608 @*/ 5609 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 5610 { 5611 DM_Plex *plex = (DM_Plex *)dm->data; 5612 PetscErrorCode ierr; 5613 5614 PetscFunctionBegin; 5615 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5616 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 5617 if (anchorSection) *anchorSection = plex->anchorSection; 5618 if (anchorIS) *anchorIS = plex->anchorIS; 5619 PetscFunctionReturn(0); 5620 } 5621 5622 #undef __FUNCT__ 5623 #define __FUNCT__ "DMPlexSetAnchors" 5624 /*@ 5625 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 5626 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 5627 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 5628 5629 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 5630 DMGetConstraints() and filling in the entries in the constraint matrix. 5631 5632 collective on dm 5633 5634 Input Parameters: 5635 + dm - The DMPlex object 5636 . 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). 5637 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 5638 5639 The reference counts of anchorSection and anchorIS are incremented. 5640 5641 Level: intermediate 5642 5643 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 5644 @*/ 5645 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 5646 { 5647 DM_Plex *plex = (DM_Plex *)dm->data; 5648 PetscMPIInt result; 5649 PetscErrorCode ierr; 5650 5651 PetscFunctionBegin; 5652 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5653 if (anchorSection) { 5654 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 5655 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 5656 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 5657 } 5658 if (anchorIS) { 5659 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 5660 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 5661 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 5662 } 5663 5664 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 5665 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 5666 plex->anchorSection = anchorSection; 5667 5668 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 5669 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 5670 plex->anchorIS = anchorIS; 5671 5672 #if defined(PETSC_USE_DEBUG) 5673 if (anchorIS && anchorSection) { 5674 PetscInt size, a, pStart, pEnd; 5675 const PetscInt *anchors; 5676 5677 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 5678 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 5679 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 5680 for (a = 0; a < size; a++) { 5681 PetscInt p; 5682 5683 p = anchors[a]; 5684 if (p >= pStart && p < pEnd) { 5685 PetscInt dof; 5686 5687 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 5688 if (dof) { 5689 PetscErrorCode ierr2; 5690 5691 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 5692 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %d cannot be constrained and an anchor",p); 5693 } 5694 } 5695 } 5696 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 5697 } 5698 #endif 5699 /* reset the generic constraints */ 5700 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 5701 PetscFunctionReturn(0); 5702 } 5703 5704 #undef __FUNCT__ 5705 #define __FUNCT__ "DMPlexCreateConstraintSection_Anchors" 5706 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 5707 { 5708 PetscSection anchorSection; 5709 PetscInt pStart, pEnd, p, dof, numFields, f; 5710 PetscErrorCode ierr; 5711 5712 PetscFunctionBegin; 5713 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5714 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 5715 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 5716 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 5717 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 5718 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 5719 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 5720 for (p = pStart; p < pEnd; p++) { 5721 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 5722 if (dof) { 5723 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 5724 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 5725 for (f = 0; f < numFields; f++) { 5726 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 5727 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 5728 } 5729 } 5730 } 5731 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 5732 PetscFunctionReturn(0); 5733 } 5734 5735 #undef __FUNCT__ 5736 #define __FUNCT__ "DMPlexCreateConstraintMatrix_Anchors" 5737 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 5738 { 5739 PetscSection aSec; 5740 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 5741 const PetscInt *anchors; 5742 PetscInt numFields, f; 5743 IS aIS; 5744 PetscErrorCode ierr; 5745 5746 PetscFunctionBegin; 5747 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5748 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 5749 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 5750 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 5751 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 5752 ierr = MatSetType(*cMat,MATSEQAIJ); 5753 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 5754 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 5755 ierr = PetscSectionGetChart(aSec,&pStart,&pEnd);CHKERRQ(ierr); 5756 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 5757 i[0] = 0; 5758 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 5759 for (p = pStart; p < pEnd; p++) { 5760 ierr = PetscSectionGetDof(aSec,p,&dof);CHKERRQ(ierr); 5761 if (!dof) continue; 5762 ierr = PetscSectionGetOffset(aSec,p,&off);CHKERRQ(ierr); 5763 if (numFields) { 5764 for (f = 0; f < numFields; f++) { 5765 annz = 0; 5766 for (q = 0; q < dof; q++) { 5767 a = anchors[off + q]; 5768 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 5769 annz += aDof; 5770 } 5771 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 5772 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 5773 for (q = 0; q < dof; q++) { 5774 i[off + q + 1] = i[off + q] + annz; 5775 } 5776 } 5777 } 5778 else { 5779 annz = 0; 5780 for (q = 0; q < dof; q++) { 5781 a = anchors[off + q]; 5782 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 5783 annz += aDof; 5784 } 5785 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 5786 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 5787 for (q = 0; q < dof; q++) { 5788 i[off + q + 1] = i[off + q] + annz; 5789 } 5790 } 5791 } 5792 nnz = i[m]; 5793 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 5794 offset = 0; 5795 for (p = pStart; p < pEnd; p++) { 5796 if (numFields) { 5797 for (f = 0; f < numFields; f++) { 5798 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 5799 for (q = 0; q < dof; q++) { 5800 PetscInt rDof, rOff, r; 5801 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 5802 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 5803 for (r = 0; r < rDof; r++) { 5804 PetscInt s; 5805 5806 a = anchors[rOff + r]; 5807 5808 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 5809 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 5810 for (s = 0; s < aDof; s++) { 5811 j[offset++] = aOff + s; 5812 } 5813 } 5814 } 5815 } 5816 } 5817 else { 5818 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 5819 for (q = 0; q < dof; q++) { 5820 PetscInt rDof, rOff, r; 5821 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 5822 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 5823 for (r = 0; r < rDof; r++) { 5824 PetscInt s; 5825 5826 a = anchors[rOff + r]; 5827 5828 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 5829 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 5830 for (s = 0; s < aDof; s++) { 5831 j[offset++] = aOff + s; 5832 } 5833 } 5834 } 5835 } 5836 } 5837 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 5838 ierr = PetscFree2(i,j);CHKERRQ(ierr); 5839 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 5840 PetscFunctionReturn(0); 5841 } 5842 5843 #undef __FUNCT__ 5844 #define __FUNCT__ "DMCreateDefaultConstraints_Plex" 5845 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 5846 { 5847 DM_Plex *plex = (DM_Plex *)dm->data; 5848 PetscSection anchorSection, section, cSec; 5849 Mat cMat; 5850 PetscErrorCode ierr; 5851 5852 PetscFunctionBegin; 5853 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5854 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 5855 if (anchorSection) { 5856 PetscDS ds; 5857 PetscInt nf; 5858 5859 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 5860 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 5861 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 5862 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 5863 ierr = PetscDSGetNumFields(ds,&nf); 5864 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 5865 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 5866 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 5867 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 5868 } 5869 PetscFunctionReturn(0); 5870 } 5871