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