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