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