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