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