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