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, j, 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 <= 1) PetscFunctionReturn(0); 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 += PetscPowInt(k+1, dim)*Nc; 3311 } 3312 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 3313 for (f = 0; f < Nf; ++f) { 3314 switch (dim) { 3315 case 2: 3316 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 3317 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, NULL);CHKERRQ(ierr); 3318 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3319 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3320 k = k/Nc + 1; 3321 /* The SEM order is 3322 3323 v_lb, {e_b}, v_rb, 3324 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 3325 v_lt, reverse {e_t}, v_rt 3326 */ 3327 { 3328 const PetscInt of = 0; 3329 const PetscInt oeb = of + PetscSqr(k-1); 3330 const PetscInt oer = oeb + (k-1); 3331 const PetscInt oet = oer + (k-1); 3332 const PetscInt oel = oet + (k-1); 3333 const PetscInt ovlb = oel + (k-1); 3334 const PetscInt ovrb = ovlb + 1; 3335 const PetscInt ovrt = ovrb + 1; 3336 const PetscInt ovlt = ovrt + 1; 3337 PetscInt o; 3338 3339 /* bottom */ 3340 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 3341 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3342 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 3343 /* middle */ 3344 for (i = 0; i < k-1; ++i) { 3345 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 3346 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; 3347 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 3348 } 3349 /* top */ 3350 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 3351 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3352 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 3353 foffset = offset; 3354 } 3355 break; 3356 case 3: 3357 /* The original hex closure is 3358 3359 {c, 3360 f_b, f_t, f_f, f_b, f_r, f_l, 3361 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 3362 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 3363 */ 3364 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, NULL);CHKERRQ(ierr); 3365 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3366 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3367 k = k/Nc + 1; 3368 /* The SEM order is 3369 Bottom Slice 3370 v_blf, {e^{(k-1)-n}_bf}, v_brf, 3371 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 3372 v_blb, {e_bb}, v_brb, 3373 3374 Middle Slice (j) 3375 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 3376 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 3377 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 3378 3379 Top Slice 3380 v_tlf, {e_tf}, v_trf, 3381 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 3382 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 3383 */ 3384 { 3385 const PetscInt oc = 0; 3386 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 3387 const PetscInt oft = ofb + PetscSqr(k-1); 3388 const PetscInt off = oft + PetscSqr(k-1); 3389 const PetscInt ofk = off + PetscSqr(k-1); 3390 const PetscInt ofr = ofk + PetscSqr(k-1); 3391 const PetscInt ofl = ofr + PetscSqr(k-1); 3392 const PetscInt oebl = ofl + PetscSqr(k-1); 3393 const PetscInt oebb = oebl + (k-1); 3394 const PetscInt oebr = oebb + (k-1); 3395 const PetscInt oebf = oebr + (k-1); 3396 const PetscInt oetf = oebf + (k-1); 3397 const PetscInt oetr = oetf + (k-1); 3398 const PetscInt oetb = oetr + (k-1); 3399 const PetscInt oetl = oetb + (k-1); 3400 const PetscInt oerf = oetl + (k-1); 3401 const PetscInt oelf = oerf + (k-1); 3402 const PetscInt oelb = oelf + (k-1); 3403 const PetscInt oerb = oelb + (k-1); 3404 const PetscInt ovblf = oerb + (k-1); 3405 const PetscInt ovblb = ovblf + 1; 3406 const PetscInt ovbrb = ovblb + 1; 3407 const PetscInt ovbrf = ovbrb + 1; 3408 const PetscInt ovtlf = ovbrf + 1; 3409 const PetscInt ovtrf = ovtlf + 1; 3410 const PetscInt ovtrb = ovtrf + 1; 3411 const PetscInt ovtlb = ovtrb + 1; 3412 PetscInt o, n; 3413 3414 /* Bottom Slice */ 3415 /* bottom */ 3416 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 3417 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3418 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 3419 /* middle */ 3420 for (i = 0; i < k-1; ++i) { 3421 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 3422 for (n = 0; n < k-1; ++n) {o = ofb+n*(k-1)+(k-2)-i; for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;} 3423 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 3424 } 3425 /* top */ 3426 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 3427 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3428 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 3429 3430 /* Middle Slice */ 3431 for (j = 0; j < k-1; ++j) { 3432 /* bottom */ 3433 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 3434 for (o = off+j*(k-1); o < off+(j+1)*(k-1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3435 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 3436 /* middle */ 3437 for (i = 0; i < k-1; ++i) { 3438 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 3439 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc+(j*(k-1)+i)*(k-1)+n)*Nc + c + foffset; 3440 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 3441 } 3442 /* top */ 3443 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 3444 for (o = ofk+j*(k-1)+(k-2); o >= ofk+j*(k-1); --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3445 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 3446 } 3447 3448 /* Top Slice */ 3449 /* bottom */ 3450 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 3451 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3452 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 3453 /* middle */ 3454 for (i = 0; i < k-1; ++i) { 3455 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 3456 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 3457 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 3458 } 3459 /* top */ 3460 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 3461 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3462 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 3463 3464 foffset = offset; 3465 } 3466 break; 3467 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", dim); 3468 } 3469 } 3470 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 3471 /* Check permutation */ 3472 { 3473 PetscInt *check; 3474 3475 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 3476 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]);} 3477 for (i = 0; i < size; ++i) check[perm[i]] = i; 3478 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 3479 ierr = PetscFree(check);CHKERRQ(ierr); 3480 } 3481 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 3482 PetscFunctionReturn(0); 3483 } 3484 3485 #undef __FUNCT__ 3486 #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static" 3487 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3488 { 3489 PetscScalar *array, *vArray; 3490 const PetscInt *cone, *coneO; 3491 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3492 PetscErrorCode ierr; 3493 3494 PetscFunctionBeginHot; 3495 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3496 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3497 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3498 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3499 if (!values || !*values) { 3500 if ((point >= pStart) && (point < pEnd)) { 3501 PetscInt dof; 3502 3503 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3504 size += dof; 3505 } 3506 for (p = 0; p < numPoints; ++p) { 3507 const PetscInt cp = cone[p]; 3508 PetscInt dof; 3509 3510 if ((cp < pStart) || (cp >= pEnd)) continue; 3511 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3512 size += dof; 3513 } 3514 if (!values) { 3515 if (csize) *csize = size; 3516 PetscFunctionReturn(0); 3517 } 3518 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 3519 } else { 3520 array = *values; 3521 } 3522 size = 0; 3523 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3524 if ((point >= pStart) && (point < pEnd)) { 3525 PetscInt dof, off, d; 3526 PetscScalar *varr; 3527 3528 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3529 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3530 varr = &vArray[off]; 3531 for (d = 0; d < dof; ++d, ++offset) { 3532 array[offset] = varr[d]; 3533 } 3534 size += dof; 3535 } 3536 for (p = 0; p < numPoints; ++p) { 3537 const PetscInt cp = cone[p]; 3538 PetscInt o = coneO[p]; 3539 PetscInt dof, off, d; 3540 PetscScalar *varr; 3541 3542 if ((cp < pStart) || (cp >= pEnd)) continue; 3543 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3544 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3545 varr = &vArray[off]; 3546 if (o >= 0) { 3547 for (d = 0; d < dof; ++d, ++offset) { 3548 array[offset] = varr[d]; 3549 } 3550 } else { 3551 for (d = dof-1; d >= 0; --d, ++offset) { 3552 array[offset] = varr[d]; 3553 } 3554 } 3555 size += dof; 3556 } 3557 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3558 if (!*values) { 3559 if (csize) *csize = size; 3560 *values = array; 3561 } else { 3562 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3563 *csize = size; 3564 } 3565 PetscFunctionReturn(0); 3566 } 3567 3568 #undef __FUNCT__ 3569 #define __FUNCT__ "DMPlexVecGetClosure_Static" 3570 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt perm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3571 { 3572 PetscInt offset = 0, p; 3573 PetscErrorCode ierr; 3574 3575 PetscFunctionBeginHot; 3576 *size = 0; 3577 for (p = 0; p < numPoints*2; p += 2) { 3578 const PetscInt point = points[p]; 3579 const PetscInt o = points[p+1]; 3580 PetscInt dof, off, d; 3581 const PetscScalar *varr; 3582 3583 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3584 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3585 varr = &vArray[off]; 3586 if (o >= 0) { 3587 for (d = 0; d < dof; ++d, ++offset) array[perm ? perm[offset] : offset] = varr[d]; 3588 } else { 3589 for (d = dof-1; d >= 0; --d, ++offset) array[perm ? perm[offset] : offset] = varr[d]; 3590 } 3591 } 3592 *size = offset; 3593 PetscFunctionReturn(0); 3594 } 3595 3596 #undef __FUNCT__ 3597 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 3598 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[]) 3599 { 3600 PetscInt offset = 0, f; 3601 PetscErrorCode ierr; 3602 3603 PetscFunctionBeginHot; 3604 *size = 0; 3605 for (f = 0; f < numFields; ++f) { 3606 PetscInt fcomp, p; 3607 3608 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3609 for (p = 0; p < numPoints*2; p += 2) { 3610 const PetscInt point = points[p]; 3611 const PetscInt o = points[p+1]; 3612 PetscInt fdof, foff, d, c; 3613 const PetscScalar *varr; 3614 3615 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3616 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3617 varr = &vArray[foff]; 3618 if (o >= 0) { 3619 for (d = 0; d < fdof; ++d, ++offset) array[perm ? perm[offset] : offset] = varr[d]; 3620 } else { 3621 for (d = fdof/fcomp-1; d >= 0; --d) { 3622 for (c = 0; c < fcomp; ++c, ++offset) { 3623 array[perm ? perm[offset] : offset] = varr[d*fcomp+c]; 3624 } 3625 } 3626 } 3627 } 3628 } 3629 *size = offset; 3630 PetscFunctionReturn(0); 3631 } 3632 3633 #undef __FUNCT__ 3634 #define __FUNCT__ "DMPlexVecGetClosure" 3635 /*@C 3636 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 3637 3638 Not collective 3639 3640 Input Parameters: 3641 + dm - The DM 3642 . section - The section describing the layout in v, or NULL to use the default section 3643 . v - The local vector 3644 - point - The sieve point in the DM 3645 3646 Output Parameters: 3647 + csize - The number of values in the closure, or NULL 3648 - values - The array of values, which is a borrowed array and should not be freed 3649 3650 Fortran Notes: 3651 Since it returns an array, this routine is only available in Fortran 90, and you must 3652 include petsc.h90 in your code. 3653 3654 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3655 3656 Level: intermediate 3657 3658 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3659 @*/ 3660 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3661 { 3662 PetscSection clSection; 3663 IS clPoints; 3664 PetscScalar *array, *vArray; 3665 PetscInt *points = NULL; 3666 const PetscInt *clp, *perm; 3667 PetscInt depth, numFields, numPoints, size; 3668 PetscErrorCode ierr; 3669 3670 PetscFunctionBeginHot; 3671 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3672 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3673 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3674 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3675 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3676 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3677 if (depth == 1 && numFields < 2) { 3678 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 3679 PetscFunctionReturn(0); 3680 } 3681 /* Get points */ 3682 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 3683 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3684 if (!clPoints) { 3685 PetscInt pStart, pEnd, p, q; 3686 3687 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3688 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3689 /* Compress out points not in the section */ 3690 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3691 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3692 points[q*2] = points[p]; 3693 points[q*2+1] = points[p+1]; 3694 ++q; 3695 } 3696 } 3697 numPoints = q; 3698 } else { 3699 PetscInt dof, off; 3700 3701 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3702 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3703 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3704 numPoints = dof/2; 3705 points = (PetscInt *) &clp[off]; 3706 } 3707 /* Get array */ 3708 if (!values || !*values) { 3709 PetscInt asize = 0, dof, p; 3710 3711 for (p = 0; p < numPoints*2; p += 2) { 3712 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3713 asize += dof; 3714 } 3715 if (!values) { 3716 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3717 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3718 if (csize) *csize = asize; 3719 PetscFunctionReturn(0); 3720 } 3721 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 3722 } else { 3723 array = *values; 3724 } 3725 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3726 /* Get values */ 3727 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 3728 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, perm, vArray, &size, array);CHKERRQ(ierr);} 3729 /* Cleanup points */ 3730 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3731 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3732 /* Cleanup array */ 3733 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3734 if (!*values) { 3735 if (csize) *csize = size; 3736 *values = array; 3737 } else { 3738 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3739 *csize = size; 3740 } 3741 PetscFunctionReturn(0); 3742 } 3743 3744 #undef __FUNCT__ 3745 #define __FUNCT__ "DMPlexVecRestoreClosure" 3746 /*@C 3747 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 3748 3749 Not collective 3750 3751 Input Parameters: 3752 + dm - The DM 3753 . section - The section describing the layout in v, or NULL to use the default section 3754 . v - The local vector 3755 . point - The sieve point in the DM 3756 . csize - The number of values in the closure, or NULL 3757 - values - The array of values, which is a borrowed array and should not be freed 3758 3759 Fortran Notes: 3760 Since it returns an array, this routine is only available in Fortran 90, and you must 3761 include petsc.h90 in your code. 3762 3763 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3764 3765 Level: intermediate 3766 3767 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3768 @*/ 3769 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3770 { 3771 PetscInt size = 0; 3772 PetscErrorCode ierr; 3773 3774 PetscFunctionBegin; 3775 /* Should work without recalculating size */ 3776 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 3777 PetscFunctionReturn(0); 3778 } 3779 3780 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 3781 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 3782 3783 #undef __FUNCT__ 3784 #define __FUNCT__ "updatePoint_private" 3785 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[]) 3786 { 3787 PetscInt cdof; /* The number of constraints on this point */ 3788 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3789 PetscScalar *a; 3790 PetscInt off, cind = 0, k; 3791 PetscErrorCode ierr; 3792 3793 PetscFunctionBegin; 3794 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3795 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3796 a = &array[off]; 3797 if (!cdof || setBC) { 3798 if (orientation >= 0) { 3799 for (k = 0; k < dof; ++k) { 3800 fuse(&a[k], values[perm ? perm[offset+k] : offset+k]); 3801 } 3802 } else { 3803 for (k = 0; k < dof; ++k) { 3804 fuse(&a[k], values[perm ? perm[offset+dof-k-1] : offset+dof-k-1]); 3805 } 3806 } 3807 } else { 3808 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3809 if (orientation >= 0) { 3810 for (k = 0; k < dof; ++k) { 3811 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3812 fuse(&a[k], values[perm ? perm[offset+k] : offset+k]); 3813 } 3814 } else { 3815 for (k = 0; k < dof; ++k) { 3816 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3817 fuse(&a[k], values[perm ? perm[offset+dof-k-1] : offset+dof-k-1]); 3818 } 3819 } 3820 } 3821 PetscFunctionReturn(0); 3822 } 3823 3824 #undef __FUNCT__ 3825 #define __FUNCT__ "updatePointBC_private" 3826 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[]) 3827 { 3828 PetscInt cdof; /* The number of constraints on this point */ 3829 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3830 PetscScalar *a; 3831 PetscInt off, cind = 0, k; 3832 PetscErrorCode ierr; 3833 3834 PetscFunctionBegin; 3835 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3836 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3837 a = &array[off]; 3838 if (cdof) { 3839 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3840 if (orientation >= 0) { 3841 for (k = 0; k < dof; ++k) { 3842 if ((cind < cdof) && (k == cdofs[cind])) { 3843 fuse(&a[k], values[perm ? perm[offset+k] : offset+k]); 3844 ++cind; 3845 } 3846 } 3847 } else { 3848 for (k = 0; k < dof; ++k) { 3849 if ((cind < cdof) && (k == cdofs[cind])) { 3850 fuse(&a[k], values[perm ? perm[offset+dof-k-1] : offset+dof-k-1]); 3851 ++cind; 3852 } 3853 } 3854 } 3855 } 3856 PetscFunctionReturn(0); 3857 } 3858 3859 #undef __FUNCT__ 3860 #define __FUNCT__ "updatePointFields_private" 3861 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[]) 3862 { 3863 PetscScalar *a; 3864 PetscInt fdof, foff, fcdof, foffset = *offset; 3865 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3866 PetscInt cind = 0, k, c; 3867 PetscErrorCode ierr; 3868 3869 PetscFunctionBegin; 3870 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3871 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3872 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3873 a = &array[foff]; 3874 if (!fcdof || setBC) { 3875 if (o >= 0) { 3876 for (k = 0; k < fdof; ++k) fuse(&a[k], values[perm ? perm[foffset+k] : foffset+k]); 3877 } else { 3878 for (k = fdof/fcomp-1; k >= 0; --k) { 3879 for (c = 0; c < fcomp; ++c) { 3880 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[perm ? perm[foffset+k*fcomp+c] : foffset+k*fcomp+c]); 3881 } 3882 } 3883 } 3884 } else { 3885 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3886 if (o >= 0) { 3887 for (k = 0; k < fdof; ++k) { 3888 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 3889 fuse(&a[k], values[perm ? perm[foffset+k] : foffset+k]); 3890 } 3891 } else { 3892 for (k = fdof/fcomp-1; k >= 0; --k) { 3893 for (c = 0; c < fcomp; ++c) { 3894 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 3895 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[perm ? perm[foffset+k*fcomp+c] : foffset+k*fcomp+c]); 3896 } 3897 } 3898 } 3899 } 3900 *offset += fdof; 3901 PetscFunctionReturn(0); 3902 } 3903 3904 #undef __FUNCT__ 3905 #define __FUNCT__ "updatePointFieldsBC_private" 3906 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[]) 3907 { 3908 PetscScalar *a; 3909 PetscInt fdof, foff, fcdof, foffset = *offset; 3910 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3911 PetscInt cind = 0, k, c; 3912 PetscErrorCode ierr; 3913 3914 PetscFunctionBegin; 3915 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3916 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3917 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3918 a = &array[foff]; 3919 if (fcdof) { 3920 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3921 if (o >= 0) { 3922 for (k = 0; k < fdof; ++k) { 3923 if ((cind < fcdof) && (k == fcdofs[cind])) { 3924 fuse(&a[k], values[perm ? perm[foffset+k] : foffset+k]); 3925 ++cind; 3926 } 3927 } 3928 } else { 3929 for (k = fdof/fcomp-1; k >= 0; --k) { 3930 for (c = 0; c < fcomp; ++c) { 3931 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 3932 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[perm ? perm[foffset+k*fcomp+c] : foffset+k*fcomp+c]); 3933 ++cind; 3934 } 3935 } 3936 } 3937 } 3938 } 3939 *offset += fdof; 3940 PetscFunctionReturn(0); 3941 } 3942 3943 #undef __FUNCT__ 3944 #define __FUNCT__ "DMPlexVecSetClosure_Depth1_Static" 3945 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3946 { 3947 PetscScalar *array; 3948 const PetscInt *cone, *coneO; 3949 PetscInt pStart, pEnd, p, numPoints, off, dof; 3950 PetscErrorCode ierr; 3951 3952 PetscFunctionBeginHot; 3953 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3954 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3955 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3956 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3957 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3958 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 3959 const PetscInt cp = !p ? point : cone[p-1]; 3960 const PetscInt o = !p ? 0 : coneO[p-1]; 3961 3962 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 3963 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3964 /* ADD_VALUES */ 3965 { 3966 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3967 PetscScalar *a; 3968 PetscInt cdof, coff, cind = 0, k; 3969 3970 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 3971 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 3972 a = &array[coff]; 3973 if (!cdof) { 3974 if (o >= 0) { 3975 for (k = 0; k < dof; ++k) { 3976 a[k] += values[off+k]; 3977 } 3978 } else { 3979 for (k = 0; k < dof; ++k) { 3980 a[k] += values[off+dof-k-1]; 3981 } 3982 } 3983 } else { 3984 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 3985 if (o >= 0) { 3986 for (k = 0; k < dof; ++k) { 3987 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3988 a[k] += values[off+k]; 3989 } 3990 } else { 3991 for (k = 0; k < dof; ++k) { 3992 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3993 a[k] += values[off+dof-k-1]; 3994 } 3995 } 3996 } 3997 } 3998 } 3999 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4000 PetscFunctionReturn(0); 4001 } 4002 4003 #undef __FUNCT__ 4004 #define __FUNCT__ "DMPlexVecSetClosure" 4005 /*@C 4006 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 4007 4008 Not collective 4009 4010 Input Parameters: 4011 + dm - The DM 4012 . section - The section describing the layout in v, or NULL to use the default section 4013 . v - The local vector 4014 . point - The sieve point in the DM 4015 . values - The array of values 4016 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4017 4018 Fortran Notes: 4019 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4020 4021 Level: intermediate 4022 4023 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 4024 @*/ 4025 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4026 { 4027 PetscSection clSection; 4028 IS clPoints; 4029 PetscScalar *array; 4030 PetscInt *points = NULL; 4031 const PetscInt *clp, *perm; 4032 PetscInt depth, numFields, numPoints, p; 4033 PetscErrorCode ierr; 4034 4035 PetscFunctionBeginHot; 4036 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4037 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4038 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4039 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4040 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4041 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4042 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 4043 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 4044 PetscFunctionReturn(0); 4045 } 4046 /* Get points */ 4047 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4048 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4049 if (!clPoints) { 4050 PetscInt pStart, pEnd, q; 4051 4052 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4053 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4054 /* Compress out points not in the section */ 4055 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4056 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4057 points[q*2] = points[p]; 4058 points[q*2+1] = points[p+1]; 4059 ++q; 4060 } 4061 } 4062 numPoints = q; 4063 } else { 4064 PetscInt dof, off; 4065 4066 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4067 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4068 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4069 numPoints = dof/2; 4070 points = (PetscInt *) &clp[off]; 4071 } 4072 /* Get array */ 4073 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4074 /* Get values */ 4075 if (numFields > 0) { 4076 PetscInt offset = 0, fcomp, f; 4077 for (f = 0; f < numFields; ++f) { 4078 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4079 switch (mode) { 4080 case INSERT_VALUES: 4081 for (p = 0; p < numPoints*2; p += 2) { 4082 const PetscInt point = points[p]; 4083 const PetscInt o = points[p+1]; 4084 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, perm, values, &offset, array); 4085 } break; 4086 case INSERT_ALL_VALUES: 4087 for (p = 0; p < numPoints*2; p += 2) { 4088 const PetscInt point = points[p]; 4089 const PetscInt o = points[p+1]; 4090 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, perm, values, &offset, array); 4091 } break; 4092 case INSERT_BC_VALUES: 4093 for (p = 0; p < numPoints*2; p += 2) { 4094 const PetscInt point = points[p]; 4095 const PetscInt o = points[p+1]; 4096 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, perm, values, &offset, array); 4097 } break; 4098 case ADD_VALUES: 4099 for (p = 0; p < numPoints*2; p += 2) { 4100 const PetscInt point = points[p]; 4101 const PetscInt o = points[p+1]; 4102 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, perm, values, &offset, array); 4103 } break; 4104 case ADD_ALL_VALUES: 4105 for (p = 0; p < numPoints*2; p += 2) { 4106 const PetscInt point = points[p]; 4107 const PetscInt o = points[p+1]; 4108 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, perm, values, &offset, array); 4109 } break; 4110 case ADD_BC_VALUES: 4111 for (p = 0; p < numPoints*2; p += 2) { 4112 const PetscInt point = points[p]; 4113 const PetscInt o = points[p+1]; 4114 updatePointFieldsBC_private(section, point, o, f, fcomp, add, perm, values, &offset, array); 4115 } break; 4116 default: 4117 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4118 } 4119 } 4120 } else { 4121 PetscInt dof, off; 4122 4123 switch (mode) { 4124 case INSERT_VALUES: 4125 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4126 PetscInt o = points[p+1]; 4127 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4128 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, perm, values, off, array); 4129 } break; 4130 case INSERT_ALL_VALUES: 4131 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4132 PetscInt o = points[p+1]; 4133 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4134 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, perm, values, off, array); 4135 } break; 4136 case INSERT_BC_VALUES: 4137 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4138 PetscInt o = points[p+1]; 4139 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4140 updatePointBC_private(section, points[p], dof, insert, o, perm, values, off, array); 4141 } break; 4142 case ADD_VALUES: 4143 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4144 PetscInt o = points[p+1]; 4145 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4146 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, perm, values, off, array); 4147 } break; 4148 case ADD_ALL_VALUES: 4149 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4150 PetscInt o = points[p+1]; 4151 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4152 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, perm, values, off, array); 4153 } break; 4154 case ADD_BC_VALUES: 4155 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4156 PetscInt o = points[p+1]; 4157 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4158 updatePointBC_private(section, points[p], dof, add, o, perm, values, off, array); 4159 } break; 4160 default: 4161 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4162 } 4163 } 4164 /* Cleanup points */ 4165 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4166 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4167 /* Cleanup array */ 4168 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4169 PetscFunctionReturn(0); 4170 } 4171 4172 #undef __FUNCT__ 4173 #define __FUNCT__ "DMPlexVecSetFieldClosure_Internal" 4174 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, const PetscScalar values[], InsertMode mode) 4175 { 4176 PetscSection clSection; 4177 IS clPoints; 4178 PetscScalar *array; 4179 PetscInt *points = NULL; 4180 const PetscInt *clp, *perm; 4181 PetscInt numFields, numPoints, p; 4182 PetscInt offset = 0, fcomp, f; 4183 PetscErrorCode ierr; 4184 4185 PetscFunctionBeginHot; 4186 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4187 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4188 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4189 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4190 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4191 /* Get points */ 4192 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4193 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4194 if (!clPoints) { 4195 PetscInt pStart, pEnd, q; 4196 4197 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4198 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4199 /* Compress out points not in the section */ 4200 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4201 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4202 points[q*2] = points[p]; 4203 points[q*2+1] = points[p+1]; 4204 ++q; 4205 } 4206 } 4207 numPoints = q; 4208 } else { 4209 PetscInt dof, off; 4210 4211 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4212 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4213 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4214 numPoints = dof/2; 4215 points = (PetscInt *) &clp[off]; 4216 } 4217 /* Get array */ 4218 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4219 /* Get values */ 4220 for (f = 0; f < numFields; ++f) { 4221 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4222 if (!fieldActive[f]) { 4223 for (p = 0; p < numPoints*2; p += 2) { 4224 PetscInt fdof; 4225 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4226 offset += fdof; 4227 } 4228 continue; 4229 } 4230 switch (mode) { 4231 case INSERT_VALUES: 4232 for (p = 0; p < numPoints*2; p += 2) { 4233 const PetscInt point = points[p]; 4234 const PetscInt o = points[p+1]; 4235 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, perm, values, &offset, array); 4236 } break; 4237 case INSERT_ALL_VALUES: 4238 for (p = 0; p < numPoints*2; p += 2) { 4239 const PetscInt point = points[p]; 4240 const PetscInt o = points[p+1]; 4241 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, perm, values, &offset, array); 4242 } break; 4243 case INSERT_BC_VALUES: 4244 for (p = 0; p < numPoints*2; p += 2) { 4245 const PetscInt point = points[p]; 4246 const PetscInt o = points[p+1]; 4247 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, perm, values, &offset, array); 4248 } break; 4249 case ADD_VALUES: 4250 for (p = 0; p < numPoints*2; p += 2) { 4251 const PetscInt point = points[p]; 4252 const PetscInt o = points[p+1]; 4253 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, perm, values, &offset, array); 4254 } break; 4255 case ADD_ALL_VALUES: 4256 for (p = 0; p < numPoints*2; p += 2) { 4257 const PetscInt point = points[p]; 4258 const PetscInt o = points[p+1]; 4259 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, perm, values, &offset, array); 4260 } break; 4261 default: 4262 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4263 } 4264 } 4265 /* Cleanup points */ 4266 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4267 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4268 /* Cleanup array */ 4269 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4270 PetscFunctionReturn(0); 4271 } 4272 4273 #undef __FUNCT__ 4274 #define __FUNCT__ "DMPlexPrintMatSetValues" 4275 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4276 { 4277 PetscMPIInt rank; 4278 PetscInt i, j; 4279 PetscErrorCode ierr; 4280 4281 PetscFunctionBegin; 4282 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4283 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 4284 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4285 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4286 numCIndices = numCIndices ? numCIndices : numRIndices; 4287 for (i = 0; i < numRIndices; i++) { 4288 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4289 for (j = 0; j < numCIndices; j++) { 4290 #if defined(PETSC_USE_COMPLEX) 4291 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4292 #else 4293 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4294 #endif 4295 } 4296 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4297 } 4298 PetscFunctionReturn(0); 4299 } 4300 4301 #undef __FUNCT__ 4302 #define __FUNCT__ "DMPlexGetIndicesPoint_Internal" 4303 /* . off - The global offset of this point */ 4304 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4305 { 4306 PetscInt dof; /* The number of unknowns on this point */ 4307 PetscInt cdof; /* The number of constraints on this point */ 4308 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4309 PetscInt cind = 0, k; 4310 PetscErrorCode ierr; 4311 4312 PetscFunctionBegin; 4313 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4314 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4315 if (!cdof || setBC) { 4316 if (orientation >= 0) { 4317 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 4318 } else { 4319 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 4320 } 4321 } else { 4322 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4323 if (orientation >= 0) { 4324 for (k = 0; k < dof; ++k) { 4325 if ((cind < cdof) && (k == cdofs[cind])) { 4326 /* Insert check for returning constrained indices */ 4327 indices[*loff+k] = -(off+k+1); 4328 ++cind; 4329 } else { 4330 indices[*loff+k] = off+k-cind; 4331 } 4332 } 4333 } else { 4334 for (k = 0; k < dof; ++k) { 4335 if ((cind < cdof) && (k == cdofs[cind])) { 4336 /* Insert check for returning constrained indices */ 4337 indices[*loff+dof-k-1] = -(off+k+1); 4338 ++cind; 4339 } else { 4340 indices[*loff+dof-k-1] = off+k-cind; 4341 } 4342 } 4343 } 4344 } 4345 *loff += dof; 4346 PetscFunctionReturn(0); 4347 } 4348 4349 #undef __FUNCT__ 4350 #define __FUNCT__ "DMPlexGetIndicesPointFields_Internal" 4351 /* . off - The global offset of this point */ 4352 PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4353 { 4354 PetscInt numFields, foff, f; 4355 PetscErrorCode ierr; 4356 4357 PetscFunctionBegin; 4358 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4359 for (f = 0, foff = 0; f < numFields; ++f) { 4360 PetscInt fdof, fcomp, cfdof; 4361 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4362 PetscInt cind = 0, k, c; 4363 4364 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4365 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4366 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4367 if (!cfdof || setBC) { 4368 if (orientation >= 0) { 4369 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 4370 } else { 4371 for (k = fdof/fcomp-1; k >= 0; --k) { 4372 for (c = 0; c < fcomp; ++c) { 4373 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 4374 } 4375 } 4376 } 4377 } else { 4378 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4379 if (orientation >= 0) { 4380 for (k = 0; k < fdof; ++k) { 4381 if ((cind < cfdof) && (k == fcdofs[cind])) { 4382 indices[foffs[f]+k] = -(off+foff+k+1); 4383 ++cind; 4384 } else { 4385 indices[foffs[f]+k] = off+foff+k-cind; 4386 } 4387 } 4388 } else { 4389 for (k = fdof/fcomp-1; k >= 0; --k) { 4390 for (c = 0; c < fcomp; ++c) { 4391 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 4392 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 4393 ++cind; 4394 } else { 4395 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 4396 } 4397 } 4398 } 4399 } 4400 } 4401 foff += (setBC ? fdof : (fdof - cfdof)); 4402 foffs[f] += fdof; 4403 } 4404 PetscFunctionReturn(0); 4405 } 4406 4407 #undef __FUNCT__ 4408 #define __FUNCT__ "DMPlexAnchorsModifyMat" 4409 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) 4410 { 4411 Mat cMat; 4412 PetscSection aSec, cSec; 4413 IS aIS; 4414 PetscInt aStart = -1, aEnd = -1; 4415 const PetscInt *anchors; 4416 PetscInt numFields, f, p, q, newP = 0; 4417 PetscInt newNumPoints = 0, newNumIndices = 0; 4418 PetscInt *newPoints, *indices, *newIndices; 4419 PetscInt maxAnchor, maxDof; 4420 PetscInt newOffsets[32]; 4421 PetscInt *pointMatOffsets[32]; 4422 PetscInt *newPointOffsets[32]; 4423 PetscScalar *pointMat[32]; 4424 PetscScalar *newValues=NULL,*tmpValues; 4425 PetscBool anyConstrained = PETSC_FALSE; 4426 PetscErrorCode ierr; 4427 4428 PetscFunctionBegin; 4429 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4430 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4431 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4432 4433 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4434 /* if there are point-to-point constraints */ 4435 if (aSec) { 4436 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4437 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 4438 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 4439 /* figure out how many points are going to be in the new element matrix 4440 * (we allow double counting, because it's all just going to be summed 4441 * into the global matrix anyway) */ 4442 for (p = 0; p < 2*numPoints; p+=2) { 4443 PetscInt b = points[p]; 4444 PetscInt bDof = 0, bSecDof; 4445 4446 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4447 if (!bSecDof) { 4448 continue; 4449 } 4450 if (b >= aStart && b < aEnd) { 4451 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4452 } 4453 if (bDof) { 4454 /* this point is constrained */ 4455 /* it is going to be replaced by its anchors */ 4456 PetscInt bOff, q; 4457 4458 anyConstrained = PETSC_TRUE; 4459 newNumPoints += bDof; 4460 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4461 for (q = 0; q < bDof; q++) { 4462 PetscInt a = anchors[bOff + q]; 4463 PetscInt aDof; 4464 4465 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4466 newNumIndices += aDof; 4467 for (f = 0; f < numFields; ++f) { 4468 PetscInt fDof; 4469 4470 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4471 newOffsets[f+1] += fDof; 4472 } 4473 } 4474 } 4475 else { 4476 /* this point is not constrained */ 4477 newNumPoints++; 4478 newNumIndices += bSecDof; 4479 for (f = 0; f < numFields; ++f) { 4480 PetscInt fDof; 4481 4482 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4483 newOffsets[f+1] += fDof; 4484 } 4485 } 4486 } 4487 } 4488 if (!anyConstrained) { 4489 if (outNumPoints) *outNumPoints = 0; 4490 if (outNumIndices) *outNumIndices = 0; 4491 if (outPoints) *outPoints = NULL; 4492 if (outValues) *outValues = NULL; 4493 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4494 PetscFunctionReturn(0); 4495 } 4496 4497 if (outNumPoints) *outNumPoints = newNumPoints; 4498 if (outNumIndices) *outNumIndices = newNumIndices; 4499 4500 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4501 4502 if (!outPoints && !outValues) { 4503 if (offsets) { 4504 for (f = 0; f <= numFields; f++) { 4505 offsets[f] = newOffsets[f]; 4506 } 4507 } 4508 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4509 PetscFunctionReturn(0); 4510 } 4511 4512 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 4513 4514 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4515 4516 /* workspaces */ 4517 if (numFields) { 4518 for (f = 0; f < numFields; f++) { 4519 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4520 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4521 } 4522 } 4523 else { 4524 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4525 ierr = DMGetWorkArray(dm,numPoints,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4526 } 4527 4528 /* get workspaces for the point-to-point matrices */ 4529 if (numFields) { 4530 PetscInt totalOffset, totalMatOffset; 4531 4532 for (p = 0; p < numPoints; p++) { 4533 PetscInt b = points[2*p]; 4534 PetscInt bDof = 0, bSecDof; 4535 4536 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4537 if (!bSecDof) { 4538 for (f = 0; f < numFields; f++) { 4539 newPointOffsets[f][p + 1] = 0; 4540 pointMatOffsets[f][p + 1] = 0; 4541 } 4542 continue; 4543 } 4544 if (b >= aStart && b < aEnd) { 4545 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4546 } 4547 if (bDof) { 4548 for (f = 0; f < numFields; f++) { 4549 PetscInt fDof, q, bOff, allFDof = 0; 4550 4551 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4552 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4553 for (q = 0; q < bDof; q++) { 4554 PetscInt a = anchors[bOff + q]; 4555 PetscInt aFDof; 4556 4557 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4558 allFDof += aFDof; 4559 } 4560 newPointOffsets[f][p+1] = allFDof; 4561 pointMatOffsets[f][p+1] = fDof * allFDof; 4562 } 4563 } 4564 else { 4565 for (f = 0; f < numFields; f++) { 4566 PetscInt fDof; 4567 4568 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4569 newPointOffsets[f][p+1] = fDof; 4570 pointMatOffsets[f][p+1] = 0; 4571 } 4572 } 4573 } 4574 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 4575 newPointOffsets[f][0] = totalOffset; 4576 pointMatOffsets[f][0] = totalMatOffset; 4577 for (p = 0; p < numPoints; p++) { 4578 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 4579 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 4580 } 4581 totalOffset = newPointOffsets[f][numPoints]; 4582 totalMatOffset = pointMatOffsets[f][numPoints]; 4583 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4584 } 4585 } 4586 else { 4587 for (p = 0; p < numPoints; p++) { 4588 PetscInt b = points[2*p]; 4589 PetscInt bDof = 0, bSecDof; 4590 4591 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4592 if (!bSecDof) { 4593 newPointOffsets[0][p + 1] = 0; 4594 pointMatOffsets[0][p + 1] = 0; 4595 continue; 4596 } 4597 if (b >= aStart && b < aEnd) { 4598 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4599 } 4600 if (bDof) { 4601 PetscInt bOff, q, allDof = 0; 4602 4603 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4604 for (q = 0; q < bDof; q++) { 4605 PetscInt a = anchors[bOff + q], aDof; 4606 4607 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 4608 allDof += aDof; 4609 } 4610 newPointOffsets[0][p+1] = allDof; 4611 pointMatOffsets[0][p+1] = bSecDof * allDof; 4612 } 4613 else { 4614 newPointOffsets[0][p+1] = bSecDof; 4615 pointMatOffsets[0][p+1] = 0; 4616 } 4617 } 4618 newPointOffsets[0][0] = 0; 4619 pointMatOffsets[0][0] = 0; 4620 for (p = 0; p < numPoints; p++) { 4621 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 4622 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 4623 } 4624 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4625 } 4626 4627 /* output arrays */ 4628 ierr = DMGetWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4629 4630 /* get the point-to-point matrices; construct newPoints */ 4631 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 4632 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4633 ierr = DMGetWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4634 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4635 if (numFields) { 4636 for (p = 0, newP = 0; p < numPoints; p++) { 4637 PetscInt b = points[2*p]; 4638 PetscInt o = points[2*p+1]; 4639 PetscInt bDof = 0, bSecDof; 4640 4641 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 4642 if (!bSecDof) { 4643 continue; 4644 } 4645 if (b >= aStart && b < aEnd) { 4646 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4647 } 4648 if (bDof) { 4649 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 4650 4651 fStart[0] = 0; 4652 fEnd[0] = 0; 4653 for (f = 0; f < numFields; f++) { 4654 PetscInt fDof; 4655 4656 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 4657 fStart[f+1] = fStart[f] + fDof; 4658 fEnd[f+1] = fStart[f+1]; 4659 } 4660 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4661 ierr = DMPlexGetIndicesPointFields_Internal(cSec, b, bOff, fEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4662 4663 fAnchorStart[0] = 0; 4664 fAnchorEnd[0] = 0; 4665 for (f = 0; f < numFields; f++) { 4666 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 4667 4668 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 4669 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 4670 } 4671 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4672 for (q = 0; q < bDof; q++) { 4673 PetscInt a = anchors[bOff + q], aOff; 4674 4675 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4676 newPoints[2*(newP + q)] = a; 4677 newPoints[2*(newP + q) + 1] = 0; 4678 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4679 ierr = DMPlexGetIndicesPointFields_Internal(section, a, aOff, fAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4680 } 4681 newP += bDof; 4682 4683 if (outValues) { 4684 /* get the point-to-point submatrix */ 4685 for (f = 0; f < numFields; f++) { 4686 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 4687 } 4688 } 4689 } 4690 else { 4691 newPoints[2 * newP] = b; 4692 newPoints[2 * newP + 1] = o; 4693 newP++; 4694 } 4695 } 4696 } else { 4697 for (p = 0; p < numPoints; p++) { 4698 PetscInt b = points[2*p]; 4699 PetscInt o = points[2*p+1]; 4700 PetscInt bDof = 0, bSecDof; 4701 4702 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 4703 if (!bSecDof) { 4704 continue; 4705 } 4706 if (b >= aStart && b < aEnd) { 4707 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4708 } 4709 if (bDof) { 4710 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 4711 4712 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4713 ierr = DMPlexGetIndicesPoint_Internal(cSec, b, bOff, &bEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4714 4715 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4716 for (q = 0; q < bDof; q++) { 4717 PetscInt a = anchors[bOff + q], aOff; 4718 4719 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4720 4721 newPoints[2*(newP + q)] = a; 4722 newPoints[2*(newP + q) + 1] = 0; 4723 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4724 ierr = DMPlexGetIndicesPoint_Internal(section, a, aOff, &bAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4725 } 4726 newP += bDof; 4727 4728 /* get the point-to-point submatrix */ 4729 if (outValues) { 4730 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 4731 } 4732 } 4733 else { 4734 newPoints[2 * newP] = b; 4735 newPoints[2 * newP + 1] = o; 4736 newP++; 4737 } 4738 } 4739 } 4740 4741 if (outValues) { 4742 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4743 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 4744 /* multiply constraints on the right */ 4745 if (numFields) { 4746 for (f = 0; f < numFields; f++) { 4747 PetscInt oldOff = offsets[f]; 4748 4749 for (p = 0; p < numPoints; p++) { 4750 PetscInt cStart = newPointOffsets[f][p]; 4751 PetscInt b = points[2 * p]; 4752 PetscInt c, r, k; 4753 PetscInt dof; 4754 4755 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4756 if (!dof) { 4757 continue; 4758 } 4759 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4760 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 4761 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 4762 4763 for (r = 0; r < numIndices; r++) { 4764 for (c = 0; c < nCols; c++) { 4765 for (k = 0; k < dof; k++) { 4766 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4767 } 4768 } 4769 } 4770 } 4771 else { 4772 /* copy this column as is */ 4773 for (r = 0; r < numIndices; r++) { 4774 for (c = 0; c < dof; c++) { 4775 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4776 } 4777 } 4778 } 4779 oldOff += dof; 4780 } 4781 } 4782 } 4783 else { 4784 PetscInt oldOff = 0; 4785 for (p = 0; p < numPoints; p++) { 4786 PetscInt cStart = newPointOffsets[0][p]; 4787 PetscInt b = points[2 * p]; 4788 PetscInt c, r, k; 4789 PetscInt dof; 4790 4791 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4792 if (!dof) { 4793 continue; 4794 } 4795 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4796 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 4797 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 4798 4799 for (r = 0; r < numIndices; r++) { 4800 for (c = 0; c < nCols; c++) { 4801 for (k = 0; k < dof; k++) { 4802 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4803 } 4804 } 4805 } 4806 } 4807 else { 4808 /* copy this column as is */ 4809 for (r = 0; r < numIndices; r++) { 4810 for (c = 0; c < dof; c++) { 4811 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4812 } 4813 } 4814 } 4815 oldOff += dof; 4816 } 4817 } 4818 4819 if (multiplyLeft) { 4820 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4821 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 4822 /* multiply constraints transpose on the left */ 4823 if (numFields) { 4824 for (f = 0; f < numFields; f++) { 4825 PetscInt oldOff = offsets[f]; 4826 4827 for (p = 0; p < numPoints; p++) { 4828 PetscInt rStart = newPointOffsets[f][p]; 4829 PetscInt b = points[2 * p]; 4830 PetscInt c, r, k; 4831 PetscInt dof; 4832 4833 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4834 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4835 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 4836 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 4837 4838 for (r = 0; r < nRows; r++) { 4839 for (c = 0; c < newNumIndices; c++) { 4840 for (k = 0; k < dof; k++) { 4841 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4842 } 4843 } 4844 } 4845 } 4846 else { 4847 /* copy this row as is */ 4848 for (r = 0; r < dof; r++) { 4849 for (c = 0; c < newNumIndices; c++) { 4850 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4851 } 4852 } 4853 } 4854 oldOff += dof; 4855 } 4856 } 4857 } 4858 else { 4859 PetscInt oldOff = 0; 4860 4861 for (p = 0; p < numPoints; p++) { 4862 PetscInt rStart = newPointOffsets[0][p]; 4863 PetscInt b = points[2 * p]; 4864 PetscInt c, r, k; 4865 PetscInt dof; 4866 4867 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4868 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4869 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 4870 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 4871 4872 for (r = 0; r < nRows; r++) { 4873 for (c = 0; c < newNumIndices; c++) { 4874 for (k = 0; k < dof; k++) { 4875 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4876 } 4877 } 4878 } 4879 } 4880 else { 4881 /* copy this row as is */ 4882 for (r = 0; r < dof; r++) { 4883 for (c = 0; c < newNumIndices; c++) { 4884 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4885 } 4886 } 4887 } 4888 oldOff += dof; 4889 } 4890 } 4891 4892 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4893 } 4894 else { 4895 newValues = tmpValues; 4896 } 4897 } 4898 4899 /* clean up */ 4900 ierr = DMRestoreWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4901 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4902 4903 if (numFields) { 4904 for (f = 0; f < numFields; f++) { 4905 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4906 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4907 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4908 } 4909 } 4910 else { 4911 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4912 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4913 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4914 } 4915 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4916 4917 /* output */ 4918 if (outPoints) { 4919 *outPoints = newPoints; 4920 } 4921 else { 4922 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4923 } 4924 if (outValues) { 4925 *outValues = newValues; 4926 } 4927 for (f = 0; f <= numFields; f++) { 4928 offsets[f] = newOffsets[f]; 4929 } 4930 PetscFunctionReturn(0); 4931 } 4932 4933 #undef __FUNCT__ 4934 #define __FUNCT__ "DMPlexGetClosureIndices" 4935 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 4936 { 4937 PetscSection clSection; 4938 IS clPoints; 4939 const PetscInt *clp; 4940 PetscInt *points = NULL, *pointsNew; 4941 PetscInt numPoints, numPointsNew; 4942 PetscInt offsets[32]; 4943 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 4944 PetscErrorCode ierr; 4945 4946 PetscFunctionBegin; 4947 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4948 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4949 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4950 if (numIndices) PetscValidPointer(numIndices, 4); 4951 PetscValidPointer(indices, 5); 4952 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4953 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 4954 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4955 /* Get points in closure */ 4956 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4957 if (!clPoints) { 4958 PetscInt pStart, pEnd, q; 4959 4960 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4961 /* Compress out points not in the section */ 4962 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4963 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4964 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4965 points[q*2] = points[p]; 4966 points[q*2+1] = points[p+1]; 4967 ++q; 4968 } 4969 } 4970 numPoints = q; 4971 } else { 4972 PetscInt dof, off; 4973 4974 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4975 numPoints = dof/2; 4976 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4977 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4978 points = (PetscInt *) &clp[off]; 4979 } 4980 /* Get number of indices and indices per field */ 4981 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 4982 PetscInt dof, fdof; 4983 4984 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4985 for (f = 0; f < Nf; ++f) { 4986 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4987 offsets[f+1] += fdof; 4988 } 4989 Nind += dof; 4990 } 4991 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 4992 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[Nf], Nind); 4993 /* Correct for hanging node constraints */ 4994 { 4995 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 4996 if (numPointsNew) { 4997 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4998 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4999 numPoints = numPointsNew; 5000 Nind = NindNew; 5001 points = pointsNew; 5002 } 5003 } 5004 /* Calculate indices */ 5005 ierr = DMGetWorkArray(dm, Nind, PETSC_INT, indices);CHKERRQ(ierr); 5006 if (Nf) { 5007 if (outOffsets) { 5008 PetscInt f; 5009 5010 for (f = 0; f <= Nf; f++) { 5011 outOffsets[f] = offsets[f]; 5012 } 5013 } 5014 for (p = 0; p < numPoints*2; p += 2) { 5015 PetscInt o = points[p+1]; 5016 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5017 DMPlexGetIndicesPointFields_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, *indices); 5018 } 5019 } else { 5020 for (p = 0, off = 0; p < numPoints*2; p += 2) { 5021 PetscInt o = points[p+1]; 5022 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5023 DMPlexGetIndicesPoint_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, *indices); 5024 } 5025 } 5026 /* Cleanup points */ 5027 if (numPointsNew) { 5028 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, PETSC_INT, &pointsNew);CHKERRQ(ierr); 5029 } else { 5030 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 5031 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 5032 } 5033 if (numIndices) *numIndices = Nind; 5034 PetscFunctionReturn(0); 5035 } 5036 5037 #undef __FUNCT__ 5038 #define __FUNCT__ "DMPlexRestoreClosureIndices" 5039 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 5040 { 5041 PetscErrorCode ierr; 5042 5043 PetscFunctionBegin; 5044 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5045 PetscValidPointer(indices, 5); 5046 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, indices);CHKERRQ(ierr); 5047 PetscFunctionReturn(0); 5048 } 5049 5050 #undef __FUNCT__ 5051 #define __FUNCT__ "DMPlexMatSetClosure" 5052 /*@C 5053 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 5054 5055 Not collective 5056 5057 Input Parameters: 5058 + dm - The DM 5059 . section - The section describing the layout in v, or NULL to use the default section 5060 . globalSection - The section describing the layout in v, or NULL to use the default global section 5061 . A - The matrix 5062 . point - The sieve point in the DM 5063 . values - The array of values 5064 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 5065 5066 Fortran Notes: 5067 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5068 5069 Level: intermediate 5070 5071 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 5072 @*/ 5073 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5074 { 5075 DM_Plex *mesh = (DM_Plex*) dm->data; 5076 PetscSection clSection; 5077 IS clPoints; 5078 PetscInt *points = NULL, *newPoints; 5079 const PetscInt *clp; 5080 PetscInt *indices; 5081 PetscInt offsets[32]; 5082 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 5083 PetscScalar *newValues; 5084 PetscErrorCode ierr; 5085 5086 PetscFunctionBegin; 5087 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5088 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 5089 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5090 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 5091 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5092 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 5093 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5094 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5095 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5096 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 5097 if (!clPoints) { 5098 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5099 /* Compress out points not in the section */ 5100 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5101 for (p = 0, q = 0; p < numPoints*2; p += 2) { 5102 if ((points[p] >= pStart) && (points[p] < pEnd)) { 5103 points[q*2] = points[p]; 5104 points[q*2+1] = points[p+1]; 5105 ++q; 5106 } 5107 } 5108 numPoints = q; 5109 } else { 5110 PetscInt dof, off; 5111 5112 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 5113 numPoints = dof/2; 5114 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 5115 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 5116 points = (PetscInt *) &clp[off]; 5117 } 5118 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 5119 PetscInt fdof; 5120 5121 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5122 for (f = 0; f < numFields; ++f) { 5123 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5124 offsets[f+1] += fdof; 5125 } 5126 numIndices += dof; 5127 } 5128 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 5129 5130 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 5131 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 5132 if (newNumPoints) { 5133 if (!clPoints) { 5134 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5135 } else { 5136 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 5137 } 5138 numPoints = newNumPoints; 5139 numIndices = newNumIndices; 5140 points = newPoints; 5141 values = newValues; 5142 } 5143 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 5144 if (numFields) { 5145 for (p = 0; p < numPoints*2; p += 2) { 5146 PetscInt o = points[p+1]; 5147 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5148 DMPlexGetIndicesPointFields_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 5149 } 5150 } else { 5151 for (p = 0, off = 0; p < numPoints*2; p += 2) { 5152 PetscInt o = points[p+1]; 5153 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5154 DMPlexGetIndicesPoint_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 5155 } 5156 } 5157 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 5158 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 5159 if (mesh->printFEM > 1) { 5160 PetscInt i; 5161 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 5162 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %d", indices[i]);CHKERRQ(ierr);} 5163 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5164 } 5165 if (ierr) { 5166 PetscMPIInt rank; 5167 PetscErrorCode ierr2; 5168 5169 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5170 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5171 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 5172 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 5173 CHKERRQ(ierr); 5174 } 5175 if (newNumPoints) { 5176 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 5177 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 5178 } 5179 else { 5180 if (!clPoints) { 5181 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5182 } else { 5183 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 5184 } 5185 } 5186 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 5187 PetscFunctionReturn(0); 5188 } 5189 5190 #undef __FUNCT__ 5191 #define __FUNCT__ "DMPlexMatSetClosureRefined" 5192 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5193 { 5194 DM_Plex *mesh = (DM_Plex*) dmf->data; 5195 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5196 PetscInt *cpoints = NULL; 5197 PetscInt *findices, *cindices; 5198 PetscInt foffsets[32], coffsets[32]; 5199 CellRefiner cellRefiner; 5200 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5201 PetscErrorCode ierr; 5202 5203 PetscFunctionBegin; 5204 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5205 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5206 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5207 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5208 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5209 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5210 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5211 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5212 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5213 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5214 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 5215 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5216 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5217 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5218 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5219 /* Column indices */ 5220 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5221 maxFPoints = numCPoints; 5222 /* Compress out points not in the section */ 5223 /* TODO: Squeeze out points with 0 dof as well */ 5224 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5225 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5226 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5227 cpoints[q*2] = cpoints[p]; 5228 cpoints[q*2+1] = cpoints[p+1]; 5229 ++q; 5230 } 5231 } 5232 numCPoints = q; 5233 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5234 PetscInt fdof; 5235 5236 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5237 if (!dof) continue; 5238 for (f = 0; f < numFields; ++f) { 5239 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5240 coffsets[f+1] += fdof; 5241 } 5242 numCIndices += dof; 5243 } 5244 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5245 /* Row indices */ 5246 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5247 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5248 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5249 for (r = 0, q = 0; r < numSubcells; ++r) { 5250 /* TODO Map from coarse to fine cells */ 5251 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5252 /* Compress out points not in the section */ 5253 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5254 for (p = 0; p < numFPoints*2; p += 2) { 5255 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5256 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5257 if (!dof) continue; 5258 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5259 if (s < q) continue; 5260 ftotpoints[q*2] = fpoints[p]; 5261 ftotpoints[q*2+1] = fpoints[p+1]; 5262 ++q; 5263 } 5264 } 5265 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5266 } 5267 numFPoints = q; 5268 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5269 PetscInt fdof; 5270 5271 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5272 if (!dof) continue; 5273 for (f = 0; f < numFields; ++f) { 5274 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5275 foffsets[f+1] += fdof; 5276 } 5277 numFIndices += dof; 5278 } 5279 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5280 5281 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5282 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5283 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5284 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5285 if (numFields) { 5286 for (p = 0; p < numFPoints*2; p += 2) { 5287 PetscInt o = ftotpoints[p+1]; 5288 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5289 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5290 } 5291 for (p = 0; p < numCPoints*2; p += 2) { 5292 PetscInt o = cpoints[p+1]; 5293 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5294 DMPlexGetIndicesPointFields_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5295 } 5296 } else { 5297 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5298 PetscInt o = ftotpoints[p+1]; 5299 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5300 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5301 } 5302 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5303 PetscInt o = cpoints[p+1]; 5304 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5305 DMPlexGetIndicesPoint_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5306 } 5307 } 5308 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5309 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5310 if (ierr) { 5311 PetscMPIInt rank; 5312 PetscErrorCode ierr2; 5313 5314 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5315 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5316 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5317 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 5318 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 5319 CHKERRQ(ierr); 5320 } 5321 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5322 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5323 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5324 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5325 PetscFunctionReturn(0); 5326 } 5327 5328 #undef __FUNCT__ 5329 #define __FUNCT__ "DMPlexMatGetClosureIndicesRefined" 5330 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5331 { 5332 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5333 PetscInt *cpoints = NULL; 5334 PetscInt foffsets[32], coffsets[32]; 5335 CellRefiner cellRefiner; 5336 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5337 PetscErrorCode ierr; 5338 5339 PetscFunctionBegin; 5340 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5341 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5342 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5343 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5344 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5345 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5346 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5347 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5348 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5349 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5350 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5351 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5352 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5353 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5354 /* Column indices */ 5355 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5356 maxFPoints = numCPoints; 5357 /* Compress out points not in the section */ 5358 /* TODO: Squeeze out points with 0 dof as well */ 5359 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5360 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5361 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5362 cpoints[q*2] = cpoints[p]; 5363 cpoints[q*2+1] = cpoints[p+1]; 5364 ++q; 5365 } 5366 } 5367 numCPoints = q; 5368 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5369 PetscInt fdof; 5370 5371 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5372 if (!dof) continue; 5373 for (f = 0; f < numFields; ++f) { 5374 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5375 coffsets[f+1] += fdof; 5376 } 5377 numCIndices += dof; 5378 } 5379 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5380 /* Row indices */ 5381 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5382 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5383 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5384 for (r = 0, q = 0; r < numSubcells; ++r) { 5385 /* TODO Map from coarse to fine cells */ 5386 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5387 /* Compress out points not in the section */ 5388 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5389 for (p = 0; p < numFPoints*2; p += 2) { 5390 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5391 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5392 if (!dof) continue; 5393 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5394 if (s < q) continue; 5395 ftotpoints[q*2] = fpoints[p]; 5396 ftotpoints[q*2+1] = fpoints[p+1]; 5397 ++q; 5398 } 5399 } 5400 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5401 } 5402 numFPoints = q; 5403 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5404 PetscInt fdof; 5405 5406 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5407 if (!dof) continue; 5408 for (f = 0; f < numFields; ++f) { 5409 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5410 foffsets[f+1] += fdof; 5411 } 5412 numFIndices += dof; 5413 } 5414 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5415 5416 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5417 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5418 if (numFields) { 5419 for (p = 0; p < numFPoints*2; p += 2) { 5420 PetscInt o = ftotpoints[p+1]; 5421 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5422 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5423 } 5424 for (p = 0; p < numCPoints*2; p += 2) { 5425 PetscInt o = cpoints[p+1]; 5426 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5427 DMPlexGetIndicesPointFields_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5428 } 5429 } else { 5430 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5431 PetscInt o = ftotpoints[p+1]; 5432 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5433 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5434 } 5435 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5436 PetscInt o = cpoints[p+1]; 5437 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5438 DMPlexGetIndicesPoint_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5439 } 5440 } 5441 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5442 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5443 PetscFunctionReturn(0); 5444 } 5445 5446 #undef __FUNCT__ 5447 #define __FUNCT__ "DMPlexGetHybridBounds" 5448 /*@ 5449 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5450 5451 Input Parameter: 5452 . dm - The DMPlex object 5453 5454 Output Parameters: 5455 + cMax - The first hybrid cell 5456 . fMax - The first hybrid face 5457 . eMax - The first hybrid edge 5458 - vMax - The first hybrid vertex 5459 5460 Level: developer 5461 5462 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 5463 @*/ 5464 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5465 { 5466 DM_Plex *mesh = (DM_Plex*) dm->data; 5467 PetscInt dim; 5468 PetscErrorCode ierr; 5469 5470 PetscFunctionBegin; 5471 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5472 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5473 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5474 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5475 if (eMax) *eMax = mesh->hybridPointMax[1]; 5476 if (vMax) *vMax = mesh->hybridPointMax[0]; 5477 PetscFunctionReturn(0); 5478 } 5479 5480 #undef __FUNCT__ 5481 #define __FUNCT__ "DMPlexSetHybridBounds" 5482 /*@ 5483 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 5484 5485 Input Parameters: 5486 . dm - The DMPlex object 5487 . cMax - The first hybrid cell 5488 . fMax - The first hybrid face 5489 . eMax - The first hybrid edge 5490 - vMax - The first hybrid vertex 5491 5492 Level: developer 5493 5494 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 5495 @*/ 5496 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 5497 { 5498 DM_Plex *mesh = (DM_Plex*) dm->data; 5499 PetscInt dim; 5500 PetscErrorCode ierr; 5501 5502 PetscFunctionBegin; 5503 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5504 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5505 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 5506 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 5507 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 5508 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 5509 PetscFunctionReturn(0); 5510 } 5511 5512 #undef __FUNCT__ 5513 #define __FUNCT__ "DMPlexGetVTKCellHeight" 5514 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 5515 { 5516 DM_Plex *mesh = (DM_Plex*) dm->data; 5517 5518 PetscFunctionBegin; 5519 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5520 PetscValidPointer(cellHeight, 2); 5521 *cellHeight = mesh->vtkCellHeight; 5522 PetscFunctionReturn(0); 5523 } 5524 5525 #undef __FUNCT__ 5526 #define __FUNCT__ "DMPlexSetVTKCellHeight" 5527 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 5528 { 5529 DM_Plex *mesh = (DM_Plex*) dm->data; 5530 5531 PetscFunctionBegin; 5532 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5533 mesh->vtkCellHeight = cellHeight; 5534 PetscFunctionReturn(0); 5535 } 5536 5537 #undef __FUNCT__ 5538 #define __FUNCT__ "DMPlexCreateNumbering_Private" 5539 /* We can easily have a form that takes an IS instead */ 5540 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 5541 { 5542 PetscSection section, globalSection; 5543 PetscInt *numbers, p; 5544 PetscErrorCode ierr; 5545 5546 PetscFunctionBegin; 5547 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5548 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 5549 for (p = pStart; p < pEnd; ++p) { 5550 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 5551 } 5552 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 5553 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 5554 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 5555 for (p = pStart; p < pEnd; ++p) { 5556 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 5557 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 5558 else numbers[p-pStart] += shift; 5559 } 5560 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 5561 if (globalSize) { 5562 PetscLayout layout; 5563 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 5564 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 5565 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 5566 } 5567 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5568 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 5569 PetscFunctionReturn(0); 5570 } 5571 5572 #undef __FUNCT__ 5573 #define __FUNCT__ "DMPlexCreateCellNumbering_Internal" 5574 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 5575 { 5576 PetscInt cellHeight, cStart, cEnd, cMax; 5577 PetscErrorCode ierr; 5578 5579 PetscFunctionBegin; 5580 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 5581 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5582 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5583 if (cMax >= 0 && !includeHybrid) cEnd = PetscMin(cEnd, cMax); 5584 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 5585 PetscFunctionReturn(0); 5586 } 5587 5588 #undef __FUNCT__ 5589 #define __FUNCT__ "DMPlexGetCellNumbering" 5590 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 5591 { 5592 DM_Plex *mesh = (DM_Plex*) dm->data; 5593 PetscErrorCode ierr; 5594 5595 PetscFunctionBegin; 5596 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5597 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 5598 *globalCellNumbers = mesh->globalCellNumbers; 5599 PetscFunctionReturn(0); 5600 } 5601 5602 #undef __FUNCT__ 5603 #define __FUNCT__ "DMPlexCreateVertexNumbering_Internal" 5604 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 5605 { 5606 PetscInt vStart, vEnd, vMax; 5607 PetscErrorCode ierr; 5608 5609 PetscFunctionBegin; 5610 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5611 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5612 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 5613 if (vMax >= 0 && !includeHybrid) vEnd = PetscMin(vEnd, vMax); 5614 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 5615 PetscFunctionReturn(0); 5616 } 5617 5618 #undef __FUNCT__ 5619 #define __FUNCT__ "DMPlexGetVertexNumbering" 5620 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 5621 { 5622 DM_Plex *mesh = (DM_Plex*) dm->data; 5623 PetscErrorCode ierr; 5624 5625 PetscFunctionBegin; 5626 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5627 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 5628 *globalVertexNumbers = mesh->globalVertexNumbers; 5629 PetscFunctionReturn(0); 5630 } 5631 5632 #undef __FUNCT__ 5633 #define __FUNCT__ "DMPlexCreatePointNumbering" 5634 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 5635 { 5636 IS nums[4]; 5637 PetscInt depths[4]; 5638 PetscInt depth, d, shift = 0; 5639 PetscErrorCode ierr; 5640 5641 PetscFunctionBegin; 5642 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5643 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5644 /* For unstratified meshes use dim instead of depth */ 5645 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 5646 depths[0] = depth; depths[1] = 0; 5647 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 5648 for (d = 0; d <= depth; ++d) { 5649 PetscInt pStart, pEnd, gsize; 5650 5651 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 5652 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 5653 shift += gsize; 5654 } 5655 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 5656 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 5657 PetscFunctionReturn(0); 5658 } 5659 5660 #undef __FUNCT__ 5661 #define __FUNCT__ "DMPlexCheckSymmetry" 5662 /*@ 5663 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5664 5665 Input Parameters: 5666 + dm - The DMPlex object 5667 5668 Note: This is a useful diagnostic when creating meshes programmatically. 5669 5670 Level: developer 5671 5672 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5673 @*/ 5674 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5675 { 5676 PetscSection coneSection, supportSection; 5677 const PetscInt *cone, *support; 5678 PetscInt coneSize, c, supportSize, s; 5679 PetscInt pStart, pEnd, p, csize, ssize; 5680 PetscErrorCode ierr; 5681 5682 PetscFunctionBegin; 5683 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5684 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5685 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5686 /* Check that point p is found in the support of its cone points, and vice versa */ 5687 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5688 for (p = pStart; p < pEnd; ++p) { 5689 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5690 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5691 for (c = 0; c < coneSize; ++c) { 5692 PetscBool dup = PETSC_FALSE; 5693 PetscInt d; 5694 for (d = c-1; d >= 0; --d) { 5695 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5696 } 5697 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5698 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5699 for (s = 0; s < supportSize; ++s) { 5700 if (support[s] == p) break; 5701 } 5702 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5703 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p);CHKERRQ(ierr); 5704 for (s = 0; s < coneSize; ++s) { 5705 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]);CHKERRQ(ierr); 5706 } 5707 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5708 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]);CHKERRQ(ierr); 5709 for (s = 0; s < supportSize; ++s) { 5710 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]);CHKERRQ(ierr); 5711 } 5712 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5713 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5714 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5715 } 5716 } 5717 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5718 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5719 for (s = 0; s < supportSize; ++s) { 5720 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5721 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5722 for (c = 0; c < coneSize; ++c) { 5723 if (cone[c] == p) break; 5724 } 5725 if (c >= coneSize) { 5726 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p);CHKERRQ(ierr); 5727 for (c = 0; c < supportSize; ++c) { 5728 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]);CHKERRQ(ierr); 5729 } 5730 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5731 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]);CHKERRQ(ierr); 5732 for (c = 0; c < coneSize; ++c) { 5733 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]);CHKERRQ(ierr); 5734 } 5735 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5736 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5737 } 5738 } 5739 } 5740 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5741 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5742 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5743 PetscFunctionReturn(0); 5744 } 5745 5746 #undef __FUNCT__ 5747 #define __FUNCT__ "DMPlexCheckSkeleton" 5748 /*@ 5749 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5750 5751 Input Parameters: 5752 + dm - The DMPlex object 5753 . isSimplex - Are the cells simplices or tensor products 5754 - cellHeight - Normally 0 5755 5756 Note: This is a useful diagnostic when creating meshes programmatically. 5757 5758 Level: developer 5759 5760 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5761 @*/ 5762 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5763 { 5764 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5765 PetscErrorCode ierr; 5766 5767 PetscFunctionBegin; 5768 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5769 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5770 switch (dim) { 5771 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5772 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5773 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5774 default: 5775 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5776 } 5777 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5778 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5779 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5780 cMax = cMax >= 0 ? cMax : cEnd; 5781 for (c = cStart; c < cMax; ++c) { 5782 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5783 5784 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5785 for (cl = 0; cl < closureSize*2; cl += 2) { 5786 const PetscInt p = closure[cl]; 5787 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5788 } 5789 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5790 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5791 } 5792 for (c = cMax; c < cEnd; ++c) { 5793 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5794 5795 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5796 for (cl = 0; cl < closureSize*2; cl += 2) { 5797 const PetscInt p = closure[cl]; 5798 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5799 } 5800 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5801 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5802 } 5803 PetscFunctionReturn(0); 5804 } 5805 5806 #undef __FUNCT__ 5807 #define __FUNCT__ "DMPlexCheckFaces" 5808 /*@ 5809 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5810 5811 Input Parameters: 5812 + dm - The DMPlex object 5813 . isSimplex - Are the cells simplices or tensor products 5814 - cellHeight - Normally 0 5815 5816 Note: This is a useful diagnostic when creating meshes programmatically. 5817 5818 Level: developer 5819 5820 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5821 @*/ 5822 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5823 { 5824 PetscInt pMax[4]; 5825 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5826 PetscErrorCode ierr; 5827 5828 PetscFunctionBegin; 5829 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5830 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5831 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5832 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5833 for (h = cellHeight; h < dim; ++h) { 5834 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5835 for (c = cStart; c < cEnd; ++c) { 5836 const PetscInt *cone, *ornt, *faces; 5837 PetscInt numFaces, faceSize, coneSize,f; 5838 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5839 5840 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5841 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5842 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5843 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5844 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5845 for (cl = 0; cl < closureSize*2; cl += 2) { 5846 const PetscInt p = closure[cl]; 5847 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5848 } 5849 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5850 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5851 for (f = 0; f < numFaces; ++f) { 5852 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5853 5854 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5855 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5856 const PetscInt p = fclosure[cl]; 5857 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5858 } 5859 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); 5860 for (v = 0; v < fnumCorners; ++v) { 5861 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]); 5862 } 5863 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5864 } 5865 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5866 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5867 } 5868 } 5869 PetscFunctionReturn(0); 5870 } 5871 5872 #undef __FUNCT__ 5873 #define __FUNCT__ "DMCreateInterpolation_Plex" 5874 /* Pointwise interpolation 5875 Just code FEM for now 5876 u^f = I u^c 5877 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5878 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5879 I_{ij} = psi^f_i phi^c_j 5880 */ 5881 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5882 { 5883 PetscSection gsc, gsf; 5884 PetscInt m, n; 5885 void *ctx; 5886 DM cdm; 5887 PetscBool regular; 5888 PetscErrorCode ierr; 5889 5890 PetscFunctionBegin; 5891 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5892 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5893 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5894 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5895 5896 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5897 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5898 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5899 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5900 5901 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 5902 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 5903 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5904 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5905 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 5906 /* Use naive scaling */ 5907 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5908 PetscFunctionReturn(0); 5909 } 5910 5911 #undef __FUNCT__ 5912 #define __FUNCT__ "DMCreateInjection_Plex" 5913 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 5914 { 5915 PetscErrorCode ierr; 5916 VecScatter ctx; 5917 5918 PetscFunctionBegin; 5919 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 5920 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 5921 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 5922 PetscFunctionReturn(0); 5923 } 5924 5925 #undef __FUNCT__ 5926 #define __FUNCT__ "DMCreateDefaultSection_Plex" 5927 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 5928 { 5929 PetscSection section; 5930 IS *bcPoints, *bcComps; 5931 PetscBool *isFE; 5932 PetscInt *bcFields, *numComp, *numDof; 5933 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 5934 PetscInt cStart, cEnd, cEndInterior; 5935 PetscErrorCode ierr; 5936 5937 PetscFunctionBegin; 5938 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 5939 if (!numFields) PetscFunctionReturn(0); 5940 /* FE and FV boundary conditions are handled slightly differently */ 5941 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 5942 for (f = 0; f < numFields; ++f) { 5943 PetscObject obj; 5944 PetscClassId id; 5945 5946 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5947 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 5948 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 5949 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 5950 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 5951 } 5952 /* Allocate boundary point storage for FEM boundaries */ 5953 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5954 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5955 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5956 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 5957 ierr = PetscDSGetNumBoundary(dm->prob, &numBd);CHKERRQ(ierr); 5958 for (bd = 0; bd < numBd; ++bd) { 5959 PetscInt field; 5960 PetscBool isEssential; 5961 const char *labelName; 5962 DMLabel label; 5963 5964 ierr = PetscDSGetBoundary(dm->prob, bd, &isEssential, NULL, &labelName, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5965 ierr = DMGetLabel(dm,labelName,&label);CHKERRQ(ierr); 5966 if (label && isFE[field] && isEssential) ++numBC; 5967 } 5968 /* Add ghost cell boundaries for FVM */ 5969 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 5970 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 5971 /* Constrain ghost cells for FV */ 5972 for (f = 0; f < numFields; ++f) { 5973 PetscInt *newidx, c; 5974 5975 if (isFE[f] || cEndInterior < 0) continue; 5976 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 5977 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 5978 bcFields[bc] = f; 5979 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5980 } 5981 /* Handle FEM Dirichlet boundaries */ 5982 for (bd = 0; bd < numBd; ++bd) { 5983 const char *bdLabel; 5984 DMLabel label; 5985 const PetscInt *comps; 5986 const PetscInt *values; 5987 PetscInt bd2, field, numComps, numValues; 5988 PetscBool isEssential, duplicate = PETSC_FALSE; 5989 5990 ierr = PetscDSGetBoundary(dm->prob, bd, &isEssential, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 5991 ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 5992 if (!isFE[field] || !label) continue; 5993 /* Only want to modify label once */ 5994 for (bd2 = 0; bd2 < bd; ++bd2) { 5995 const char *bdname; 5996 ierr = PetscDSGetBoundary(dm->prob, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5997 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 5998 if (duplicate) break; 5999 } 6000 if (!duplicate && (isFE[field])) { 6001 /* don't complete cells, which are just present to give orientation to the boundary */ 6002 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 6003 } 6004 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 6005 if (isEssential) { 6006 PetscInt *newidx; 6007 PetscInt n, newn = 0, p, v; 6008 6009 bcFields[bc] = field; 6010 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 6011 for (v = 0; v < numValues; ++v) { 6012 IS tmp; 6013 const PetscInt *idx; 6014 6015 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6016 if (!tmp) continue; 6017 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6018 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6019 if (isFE[field]) { 6020 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 6021 } else { 6022 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 6023 } 6024 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6025 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6026 } 6027 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 6028 newn = 0; 6029 for (v = 0; v < numValues; ++v) { 6030 IS tmp; 6031 const PetscInt *idx; 6032 6033 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6034 if (!tmp) continue; 6035 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6036 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6037 if (isFE[field]) { 6038 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 6039 } else { 6040 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 6041 } 6042 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6043 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6044 } 6045 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 6046 } 6047 } 6048 /* Handle discretization */ 6049 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 6050 for (f = 0; f < numFields; ++f) { 6051 PetscObject obj; 6052 6053 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 6054 if (isFE[f]) { 6055 PetscFE fe = (PetscFE) obj; 6056 const PetscInt *numFieldDof; 6057 PetscInt d; 6058 6059 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 6060 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 6061 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 6062 } else { 6063 PetscFV fv = (PetscFV) obj; 6064 6065 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 6066 numDof[f*(dim+1)+dim] = numComp[f]; 6067 } 6068 } 6069 for (f = 0; f < numFields; ++f) { 6070 PetscInt d; 6071 for (d = 1; d < dim; ++d) { 6072 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."); 6073 } 6074 } 6075 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 6076 for (f = 0; f < numFields; ++f) { 6077 PetscFE fe; 6078 const char *name; 6079 6080 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 6081 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 6082 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 6083 } 6084 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 6085 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6086 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 6087 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 6088 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 6089 ierr = PetscFree(isFE);CHKERRQ(ierr); 6090 PetscFunctionReturn(0); 6091 } 6092 6093 #undef __FUNCT__ 6094 #define __FUNCT__ "DMPlexGetRegularRefinement" 6095 /*@ 6096 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6097 6098 Input Parameter: 6099 . dm - The DMPlex object 6100 6101 Output Parameter: 6102 . regular - The flag 6103 6104 Level: intermediate 6105 6106 .seealso: DMPlexSetRegularRefinement() 6107 @*/ 6108 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 6109 { 6110 PetscFunctionBegin; 6111 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6112 PetscValidPointer(regular, 2); 6113 *regular = ((DM_Plex *) dm->data)->regularRefinement; 6114 PetscFunctionReturn(0); 6115 } 6116 6117 #undef __FUNCT__ 6118 #define __FUNCT__ "DMPlexSetRegularRefinement" 6119 /*@ 6120 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6121 6122 Input Parameters: 6123 + dm - The DMPlex object 6124 - regular - The flag 6125 6126 Level: intermediate 6127 6128 .seealso: DMPlexGetRegularRefinement() 6129 @*/ 6130 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 6131 { 6132 PetscFunctionBegin; 6133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6134 ((DM_Plex *) dm->data)->regularRefinement = regular; 6135 PetscFunctionReturn(0); 6136 } 6137 6138 /* anchors */ 6139 #undef __FUNCT__ 6140 #define __FUNCT__ "DMPlexGetAnchors" 6141 /*@ 6142 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 6143 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 6144 6145 not collective 6146 6147 Input Parameters: 6148 . dm - The DMPlex object 6149 6150 Output Parameters: 6151 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 6152 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 6153 6154 6155 Level: intermediate 6156 6157 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 6158 @*/ 6159 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 6160 { 6161 DM_Plex *plex = (DM_Plex *)dm->data; 6162 PetscErrorCode ierr; 6163 6164 PetscFunctionBegin; 6165 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6166 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 6167 if (anchorSection) *anchorSection = plex->anchorSection; 6168 if (anchorIS) *anchorIS = plex->anchorIS; 6169 PetscFunctionReturn(0); 6170 } 6171 6172 #undef __FUNCT__ 6173 #define __FUNCT__ "DMPlexSetAnchors" 6174 /*@ 6175 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 6176 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 6177 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 6178 6179 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 6180 DMGetConstraints() and filling in the entries in the constraint matrix. 6181 6182 collective on dm 6183 6184 Input Parameters: 6185 + dm - The DMPlex object 6186 . 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). 6187 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 6188 6189 The reference counts of anchorSection and anchorIS are incremented. 6190 6191 Level: intermediate 6192 6193 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 6194 @*/ 6195 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 6196 { 6197 DM_Plex *plex = (DM_Plex *)dm->data; 6198 PetscMPIInt result; 6199 PetscErrorCode ierr; 6200 6201 PetscFunctionBegin; 6202 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6203 if (anchorSection) { 6204 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 6205 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 6206 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 6207 } 6208 if (anchorIS) { 6209 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 6210 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 6211 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 6212 } 6213 6214 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 6215 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 6216 plex->anchorSection = anchorSection; 6217 6218 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 6219 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 6220 plex->anchorIS = anchorIS; 6221 6222 #if defined(PETSC_USE_DEBUG) 6223 if (anchorIS && anchorSection) { 6224 PetscInt size, a, pStart, pEnd; 6225 const PetscInt *anchors; 6226 6227 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6228 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 6229 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 6230 for (a = 0; a < size; a++) { 6231 PetscInt p; 6232 6233 p = anchors[a]; 6234 if (p >= pStart && p < pEnd) { 6235 PetscInt dof; 6236 6237 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6238 if (dof) { 6239 PetscErrorCode ierr2; 6240 6241 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 6242 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %d cannot be constrained and an anchor",p); 6243 } 6244 } 6245 } 6246 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 6247 } 6248 #endif 6249 /* reset the generic constraints */ 6250 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 6251 PetscFunctionReturn(0); 6252 } 6253 6254 #undef __FUNCT__ 6255 #define __FUNCT__ "DMPlexCreateConstraintSection_Anchors" 6256 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 6257 { 6258 PetscSection anchorSection; 6259 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 6260 PetscErrorCode ierr; 6261 6262 PetscFunctionBegin; 6263 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6264 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6265 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 6266 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6267 if (numFields) { 6268 PetscInt f; 6269 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 6270 6271 for (f = 0; f < numFields; f++) { 6272 PetscInt numComp; 6273 6274 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 6275 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 6276 } 6277 } 6278 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6279 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 6280 pStart = PetscMax(pStart,sStart); 6281 pEnd = PetscMin(pEnd,sEnd); 6282 pEnd = PetscMax(pStart,pEnd); 6283 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 6284 for (p = pStart; p < pEnd; p++) { 6285 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6286 if (dof) { 6287 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 6288 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 6289 for (f = 0; f < numFields; f++) { 6290 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 6291 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 6292 } 6293 } 6294 } 6295 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 6296 PetscFunctionReturn(0); 6297 } 6298 6299 #undef __FUNCT__ 6300 #define __FUNCT__ "DMPlexCreateConstraintMatrix_Anchors" 6301 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 6302 { 6303 PetscSection aSec; 6304 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 6305 const PetscInt *anchors; 6306 PetscInt numFields, f; 6307 IS aIS; 6308 PetscErrorCode ierr; 6309 6310 PetscFunctionBegin; 6311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6312 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 6313 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 6314 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 6315 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 6316 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 6317 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6318 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6319 /* cSec will be a subset of aSec and section */ 6320 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 6321 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 6322 i[0] = 0; 6323 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6324 for (p = pStart; p < pEnd; p++) { 6325 PetscInt rDof, rOff, r; 6326 6327 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6328 if (!rDof) continue; 6329 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6330 if (numFields) { 6331 for (f = 0; f < numFields; f++) { 6332 annz = 0; 6333 for (r = 0; r < rDof; r++) { 6334 a = anchors[rOff + r]; 6335 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6336 annz += aDof; 6337 } 6338 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6339 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 6340 for (q = 0; q < dof; q++) { 6341 i[off + q + 1] = i[off + q] + annz; 6342 } 6343 } 6344 } 6345 else { 6346 annz = 0; 6347 for (q = 0; q < dof; q++) { 6348 a = anchors[off + q]; 6349 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6350 annz += aDof; 6351 } 6352 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6353 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 6354 for (q = 0; q < dof; q++) { 6355 i[off + q + 1] = i[off + q] + annz; 6356 } 6357 } 6358 } 6359 nnz = i[m]; 6360 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 6361 offset = 0; 6362 for (p = pStart; p < pEnd; p++) { 6363 if (numFields) { 6364 for (f = 0; f < numFields; f++) { 6365 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6366 for (q = 0; q < dof; q++) { 6367 PetscInt rDof, rOff, r; 6368 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6369 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6370 for (r = 0; r < rDof; r++) { 6371 PetscInt s; 6372 6373 a = anchors[rOff + r]; 6374 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6375 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 6376 for (s = 0; s < aDof; s++) { 6377 j[offset++] = aOff + s; 6378 } 6379 } 6380 } 6381 } 6382 } 6383 else { 6384 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6385 for (q = 0; q < dof; q++) { 6386 PetscInt rDof, rOff, r; 6387 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6388 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6389 for (r = 0; r < rDof; r++) { 6390 PetscInt s; 6391 6392 a = anchors[rOff + r]; 6393 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6394 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 6395 for (s = 0; s < aDof; s++) { 6396 j[offset++] = aOff + s; 6397 } 6398 } 6399 } 6400 } 6401 } 6402 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 6403 ierr = PetscFree(i);CHKERRQ(ierr); 6404 ierr = PetscFree(j);CHKERRQ(ierr); 6405 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 6406 PetscFunctionReturn(0); 6407 } 6408 6409 #undef __FUNCT__ 6410 #define __FUNCT__ "DMCreateDefaultConstraints_Plex" 6411 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 6412 { 6413 DM_Plex *plex = (DM_Plex *)dm->data; 6414 PetscSection anchorSection, section, cSec; 6415 Mat cMat; 6416 PetscErrorCode ierr; 6417 6418 PetscFunctionBegin; 6419 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6420 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6421 if (anchorSection) { 6422 PetscDS ds; 6423 PetscInt nf; 6424 6425 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 6426 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 6427 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 6428 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 6429 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 6430 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 6431 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 6432 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 6433 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 6434 } 6435 PetscFunctionReturn(0); 6436 } 6437