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