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