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