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