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