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