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