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