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