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