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__ "DMPlexVecGetClosure_Depth1_Static" 3560 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3561 { 3562 PetscScalar *array, *vArray; 3563 const PetscInt *cone, *coneO; 3564 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3565 PetscErrorCode ierr; 3566 3567 PetscFunctionBeginHot; 3568 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3569 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3570 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3571 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3572 if (!values || !*values) { 3573 if ((point >= pStart) && (point < pEnd)) { 3574 PetscInt dof; 3575 3576 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3577 size += dof; 3578 } 3579 for (p = 0; p < numPoints; ++p) { 3580 const PetscInt cp = cone[p]; 3581 PetscInt dof; 3582 3583 if ((cp < pStart) || (cp >= pEnd)) continue; 3584 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3585 size += dof; 3586 } 3587 if (!values) { 3588 if (csize) *csize = size; 3589 PetscFunctionReturn(0); 3590 } 3591 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 3592 } else { 3593 array = *values; 3594 } 3595 size = 0; 3596 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3597 if ((point >= pStart) && (point < pEnd)) { 3598 PetscInt dof, off, d; 3599 PetscScalar *varr; 3600 3601 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3602 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3603 varr = &vArray[off]; 3604 for (d = 0; d < dof; ++d, ++offset) { 3605 array[offset] = varr[d]; 3606 } 3607 size += dof; 3608 } 3609 for (p = 0; p < numPoints; ++p) { 3610 const PetscInt cp = cone[p]; 3611 PetscInt o = coneO[p]; 3612 PetscInt dof, off, d; 3613 PetscScalar *varr; 3614 3615 if ((cp < pStart) || (cp >= pEnd)) continue; 3616 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3617 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3618 varr = &vArray[off]; 3619 if (o >= 0) { 3620 for (d = 0; d < dof; ++d, ++offset) { 3621 array[offset] = varr[d]; 3622 } 3623 } else { 3624 for (d = dof-1; d >= 0; --d, ++offset) { 3625 array[offset] = varr[d]; 3626 } 3627 } 3628 size += dof; 3629 } 3630 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3631 if (!*values) { 3632 if (csize) *csize = size; 3633 *values = array; 3634 } else { 3635 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3636 *csize = size; 3637 } 3638 PetscFunctionReturn(0); 3639 } 3640 3641 #undef __FUNCT__ 3642 #define __FUNCT__ "DMPlexVecGetClosure_Static" 3643 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt perm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3644 { 3645 PetscInt offset = 0, p; 3646 PetscErrorCode ierr; 3647 3648 PetscFunctionBeginHot; 3649 *size = 0; 3650 for (p = 0; p < numPoints*2; p += 2) { 3651 const PetscInt point = points[p]; 3652 const PetscInt o = points[p+1]; 3653 PetscInt dof, off, d; 3654 const PetscScalar *varr; 3655 3656 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3657 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3658 varr = &vArray[off]; 3659 if (o >= 0) { 3660 for (d = 0; d < dof; ++d, ++offset) array[perm ? perm[offset] : offset] = varr[d]; 3661 } else { 3662 for (d = dof-1; d >= 0; --d, ++offset) array[perm ? perm[offset] : offset] = varr[d]; 3663 } 3664 } 3665 *size = offset; 3666 PetscFunctionReturn(0); 3667 } 3668 3669 #undef __FUNCT__ 3670 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 3671 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscInt perm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3672 { 3673 PetscInt offset = 0, f; 3674 PetscErrorCode ierr; 3675 3676 PetscFunctionBeginHot; 3677 *size = 0; 3678 for (f = 0; f < numFields; ++f) { 3679 PetscInt fcomp, p; 3680 3681 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3682 for (p = 0; p < numPoints*2; p += 2) { 3683 const PetscInt point = points[p]; 3684 const PetscInt o = points[p+1]; 3685 PetscInt fdof, foff, d, c; 3686 const PetscScalar *varr; 3687 3688 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3689 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3690 varr = &vArray[foff]; 3691 if (o >= 0) { 3692 for (d = 0; d < fdof; ++d, ++offset) array[perm ? perm[offset] : offset] = varr[d]; 3693 } else { 3694 for (d = fdof/fcomp-1; d >= 0; --d) { 3695 for (c = 0; c < fcomp; ++c, ++offset) { 3696 array[perm ? perm[offset] : offset] = varr[d*fcomp+c]; 3697 } 3698 } 3699 } 3700 } 3701 } 3702 *size = offset; 3703 PetscFunctionReturn(0); 3704 } 3705 3706 #undef __FUNCT__ 3707 #define __FUNCT__ "DMPlexVecGetClosure" 3708 /*@C 3709 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 3710 3711 Not collective 3712 3713 Input Parameters: 3714 + dm - The DM 3715 . section - The section describing the layout in v, or NULL to use the default section 3716 . v - The local vector 3717 - point - The sieve point in the DM 3718 3719 Output Parameters: 3720 + csize - The number of values in the closure, or NULL 3721 - values - The array of values, which is a borrowed array and should not be freed 3722 3723 Fortran Notes: 3724 Since it returns an array, this routine is only available in Fortran 90, and you must 3725 include petsc.h90 in your code. 3726 3727 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3728 3729 Level: intermediate 3730 3731 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3732 @*/ 3733 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3734 { 3735 PetscSection clSection; 3736 IS clPoints; 3737 PetscScalar *array, *vArray; 3738 PetscInt *points = NULL; 3739 const PetscInt *clp, *perm; 3740 PetscInt depth, numFields, numPoints, size; 3741 PetscErrorCode ierr; 3742 3743 PetscFunctionBeginHot; 3744 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3745 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3746 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3747 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3748 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3749 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3750 if (depth == 1 && numFields < 2) { 3751 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 3752 PetscFunctionReturn(0); 3753 } 3754 /* Get points */ 3755 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 3756 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3757 if (!clPoints) { 3758 PetscInt pStart, pEnd, p, q; 3759 3760 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3761 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3762 /* Compress out points not in the section */ 3763 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3764 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3765 points[q*2] = points[p]; 3766 points[q*2+1] = points[p+1]; 3767 ++q; 3768 } 3769 } 3770 numPoints = q; 3771 } else { 3772 PetscInt dof, off; 3773 3774 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3775 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3776 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3777 numPoints = dof/2; 3778 points = (PetscInt *) &clp[off]; 3779 } 3780 /* Get array */ 3781 if (!values || !*values) { 3782 PetscInt asize = 0, dof, p; 3783 3784 for (p = 0; p < numPoints*2; p += 2) { 3785 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3786 asize += dof; 3787 } 3788 if (!values) { 3789 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3790 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3791 if (csize) *csize = asize; 3792 PetscFunctionReturn(0); 3793 } 3794 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 3795 } else { 3796 array = *values; 3797 } 3798 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3799 /* Get values */ 3800 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 3801 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, perm, vArray, &size, array);CHKERRQ(ierr);} 3802 /* Cleanup points */ 3803 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3804 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3805 /* Cleanup array */ 3806 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3807 if (!*values) { 3808 if (csize) *csize = size; 3809 *values = array; 3810 } else { 3811 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3812 *csize = size; 3813 } 3814 PetscFunctionReturn(0); 3815 } 3816 3817 #undef __FUNCT__ 3818 #define __FUNCT__ "DMPlexVecRestoreClosure" 3819 /*@C 3820 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 3821 3822 Not collective 3823 3824 Input Parameters: 3825 + dm - The DM 3826 . section - The section describing the layout in v, or NULL to use the default section 3827 . v - The local vector 3828 . point - The sieve point in the DM 3829 . csize - The number of values in the closure, or NULL 3830 - values - The array of values, which is a borrowed array and should not be freed 3831 3832 Fortran Notes: 3833 Since it returns an array, this routine is only available in Fortran 90, and you must 3834 include petsc.h90 in your code. 3835 3836 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3837 3838 Level: intermediate 3839 3840 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3841 @*/ 3842 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3843 { 3844 PetscInt size = 0; 3845 PetscErrorCode ierr; 3846 3847 PetscFunctionBegin; 3848 /* Should work without recalculating size */ 3849 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 3850 PetscFunctionReturn(0); 3851 } 3852 3853 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 3854 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 3855 3856 #undef __FUNCT__ 3857 #define __FUNCT__ "updatePoint_private" 3858 PETSC_STATIC_INLINE PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscInt perm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 3859 { 3860 PetscInt cdof; /* The number of constraints on this point */ 3861 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3862 PetscScalar *a; 3863 PetscInt off, cind = 0, k; 3864 PetscErrorCode ierr; 3865 3866 PetscFunctionBegin; 3867 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3868 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3869 a = &array[off]; 3870 if (!cdof || setBC) { 3871 if (orientation >= 0) { 3872 for (k = 0; k < dof; ++k) { 3873 fuse(&a[k], values[perm ? perm[offset+k] : offset+k]); 3874 } 3875 } else { 3876 for (k = 0; k < dof; ++k) { 3877 fuse(&a[k], values[perm ? perm[offset+dof-k-1] : offset+dof-k-1]); 3878 } 3879 } 3880 } else { 3881 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3882 if (orientation >= 0) { 3883 for (k = 0; k < dof; ++k) { 3884 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3885 fuse(&a[k], values[perm ? perm[offset+k] : offset+k]); 3886 } 3887 } else { 3888 for (k = 0; k < dof; ++k) { 3889 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3890 fuse(&a[k], values[perm ? perm[offset+dof-k-1] : offset+dof-k-1]); 3891 } 3892 } 3893 } 3894 PetscFunctionReturn(0); 3895 } 3896 3897 #undef __FUNCT__ 3898 #define __FUNCT__ "updatePointBC_private" 3899 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscInt perm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 3900 { 3901 PetscInt cdof; /* The number of constraints on this point */ 3902 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3903 PetscScalar *a; 3904 PetscInt off, cind = 0, k; 3905 PetscErrorCode ierr; 3906 3907 PetscFunctionBegin; 3908 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3909 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3910 a = &array[off]; 3911 if (cdof) { 3912 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3913 if (orientation >= 0) { 3914 for (k = 0; k < dof; ++k) { 3915 if ((cind < cdof) && (k == cdofs[cind])) { 3916 fuse(&a[k], values[perm ? perm[offset+k] : offset+k]); 3917 ++cind; 3918 } 3919 } 3920 } else { 3921 for (k = 0; k < dof; ++k) { 3922 if ((cind < cdof) && (k == cdofs[cind])) { 3923 fuse(&a[k], values[perm ? perm[offset+dof-k-1] : offset+dof-k-1]); 3924 ++cind; 3925 } 3926 } 3927 } 3928 } 3929 PetscFunctionReturn(0); 3930 } 3931 3932 #undef __FUNCT__ 3933 #define __FUNCT__ "updatePointFields_private" 3934 PETSC_STATIC_INLINE PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt perm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 3935 { 3936 PetscScalar *a; 3937 PetscInt fdof, foff, fcdof, foffset = *offset; 3938 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3939 PetscInt cind = 0, k, c; 3940 PetscErrorCode ierr; 3941 3942 PetscFunctionBegin; 3943 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3944 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3945 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3946 a = &array[foff]; 3947 if (!fcdof || setBC) { 3948 if (o >= 0) { 3949 for (k = 0; k < fdof; ++k) fuse(&a[k], values[perm ? perm[foffset+k] : foffset+k]); 3950 } else { 3951 for (k = fdof/fcomp-1; k >= 0; --k) { 3952 for (c = 0; c < fcomp; ++c) { 3953 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[perm ? perm[foffset+k*fcomp+c] : foffset+k*fcomp+c]); 3954 } 3955 } 3956 } 3957 } else { 3958 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3959 if (o >= 0) { 3960 for (k = 0; k < fdof; ++k) { 3961 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 3962 fuse(&a[k], values[perm ? perm[foffset+k] : foffset+k]); 3963 } 3964 } else { 3965 for (k = fdof/fcomp-1; k >= 0; --k) { 3966 for (c = 0; c < fcomp; ++c) { 3967 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 3968 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[perm ? perm[foffset+k*fcomp+c] : foffset+k*fcomp+c]); 3969 } 3970 } 3971 } 3972 } 3973 *offset += fdof; 3974 PetscFunctionReturn(0); 3975 } 3976 3977 #undef __FUNCT__ 3978 #define __FUNCT__ "updatePointFieldsBC_private" 3979 PETSC_STATIC_INLINE PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), const PetscInt perm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 3980 { 3981 PetscScalar *a; 3982 PetscInt fdof, foff, fcdof, foffset = *offset; 3983 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3984 PetscInt cind = 0, k, c; 3985 PetscErrorCode ierr; 3986 3987 PetscFunctionBegin; 3988 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3989 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3990 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3991 a = &array[foff]; 3992 if (fcdof) { 3993 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3994 if (o >= 0) { 3995 for (k = 0; k < fdof; ++k) { 3996 if ((cind < fcdof) && (k == fcdofs[cind])) { 3997 fuse(&a[k], values[perm ? perm[foffset+k] : foffset+k]); 3998 ++cind; 3999 } 4000 } 4001 } else { 4002 for (k = fdof/fcomp-1; k >= 0; --k) { 4003 for (c = 0; c < fcomp; ++c) { 4004 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 4005 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[perm ? perm[foffset+k*fcomp+c] : foffset+k*fcomp+c]); 4006 ++cind; 4007 } 4008 } 4009 } 4010 } 4011 } 4012 *offset += fdof; 4013 PetscFunctionReturn(0); 4014 } 4015 4016 #undef __FUNCT__ 4017 #define __FUNCT__ "DMPlexVecSetClosure_Depth1_Static" 4018 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4019 { 4020 PetscScalar *array; 4021 const PetscInt *cone, *coneO; 4022 PetscInt pStart, pEnd, p, numPoints, off, dof; 4023 PetscErrorCode ierr; 4024 4025 PetscFunctionBeginHot; 4026 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4027 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4028 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4029 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4030 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4031 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 4032 const PetscInt cp = !p ? point : cone[p-1]; 4033 const PetscInt o = !p ? 0 : coneO[p-1]; 4034 4035 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 4036 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4037 /* ADD_VALUES */ 4038 { 4039 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4040 PetscScalar *a; 4041 PetscInt cdof, coff, cind = 0, k; 4042 4043 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 4044 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 4045 a = &array[coff]; 4046 if (!cdof) { 4047 if (o >= 0) { 4048 for (k = 0; k < dof; ++k) { 4049 a[k] += values[off+k]; 4050 } 4051 } else { 4052 for (k = 0; k < dof; ++k) { 4053 a[k] += values[off+dof-k-1]; 4054 } 4055 } 4056 } else { 4057 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 4058 if (o >= 0) { 4059 for (k = 0; k < dof; ++k) { 4060 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4061 a[k] += values[off+k]; 4062 } 4063 } else { 4064 for (k = 0; k < dof; ++k) { 4065 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4066 a[k] += values[off+dof-k-1]; 4067 } 4068 } 4069 } 4070 } 4071 } 4072 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4073 PetscFunctionReturn(0); 4074 } 4075 4076 #undef __FUNCT__ 4077 #define __FUNCT__ "DMPlexVecSetClosure" 4078 /*@C 4079 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 4080 4081 Not collective 4082 4083 Input Parameters: 4084 + dm - The DM 4085 . section - The section describing the layout in v, or NULL to use the default section 4086 . v - The local vector 4087 . point - The sieve point in the DM 4088 . values - The array of values 4089 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4090 4091 Fortran Notes: 4092 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4093 4094 Level: intermediate 4095 4096 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 4097 @*/ 4098 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4099 { 4100 PetscSection clSection; 4101 IS clPoints; 4102 PetscScalar *array; 4103 PetscInt *points = NULL; 4104 const PetscInt *clp, *perm; 4105 PetscInt depth, numFields, numPoints, p; 4106 PetscErrorCode ierr; 4107 4108 PetscFunctionBeginHot; 4109 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4110 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4111 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4112 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4113 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4114 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4115 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 4116 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 4117 PetscFunctionReturn(0); 4118 } 4119 /* Get points */ 4120 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4121 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4122 if (!clPoints) { 4123 PetscInt pStart, pEnd, q; 4124 4125 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4126 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4127 /* Compress out points not in the section */ 4128 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4129 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4130 points[q*2] = points[p]; 4131 points[q*2+1] = points[p+1]; 4132 ++q; 4133 } 4134 } 4135 numPoints = q; 4136 } else { 4137 PetscInt dof, off; 4138 4139 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4140 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4141 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4142 numPoints = dof/2; 4143 points = (PetscInt *) &clp[off]; 4144 } 4145 /* Get array */ 4146 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4147 /* Get values */ 4148 if (numFields > 0) { 4149 PetscInt offset = 0, fcomp, f; 4150 for (f = 0; f < numFields; ++f) { 4151 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4152 switch (mode) { 4153 case INSERT_VALUES: 4154 for (p = 0; p < numPoints*2; p += 2) { 4155 const PetscInt point = points[p]; 4156 const PetscInt o = points[p+1]; 4157 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, perm, values, &offset, array); 4158 } break; 4159 case INSERT_ALL_VALUES: 4160 for (p = 0; p < numPoints*2; p += 2) { 4161 const PetscInt point = points[p]; 4162 const PetscInt o = points[p+1]; 4163 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, perm, values, &offset, array); 4164 } break; 4165 case INSERT_BC_VALUES: 4166 for (p = 0; p < numPoints*2; p += 2) { 4167 const PetscInt point = points[p]; 4168 const PetscInt o = points[p+1]; 4169 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, perm, values, &offset, array); 4170 } break; 4171 case ADD_VALUES: 4172 for (p = 0; p < numPoints*2; p += 2) { 4173 const PetscInt point = points[p]; 4174 const PetscInt o = points[p+1]; 4175 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, perm, values, &offset, array); 4176 } break; 4177 case ADD_ALL_VALUES: 4178 for (p = 0; p < numPoints*2; p += 2) { 4179 const PetscInt point = points[p]; 4180 const PetscInt o = points[p+1]; 4181 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, perm, values, &offset, array); 4182 } break; 4183 case ADD_BC_VALUES: 4184 for (p = 0; p < numPoints*2; p += 2) { 4185 const PetscInt point = points[p]; 4186 const PetscInt o = points[p+1]; 4187 updatePointFieldsBC_private(section, point, o, f, fcomp, add, perm, values, &offset, array); 4188 } break; 4189 default: 4190 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4191 } 4192 } 4193 } else { 4194 PetscInt dof, off; 4195 4196 switch (mode) { 4197 case INSERT_VALUES: 4198 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4199 PetscInt o = points[p+1]; 4200 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4201 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, perm, values, off, array); 4202 } break; 4203 case INSERT_ALL_VALUES: 4204 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4205 PetscInt o = points[p+1]; 4206 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4207 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, perm, values, off, array); 4208 } break; 4209 case INSERT_BC_VALUES: 4210 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4211 PetscInt o = points[p+1]; 4212 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4213 updatePointBC_private(section, points[p], dof, insert, o, perm, values, off, array); 4214 } break; 4215 case ADD_VALUES: 4216 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4217 PetscInt o = points[p+1]; 4218 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4219 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, perm, values, off, array); 4220 } break; 4221 case ADD_ALL_VALUES: 4222 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4223 PetscInt o = points[p+1]; 4224 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4225 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, perm, values, off, array); 4226 } break; 4227 case ADD_BC_VALUES: 4228 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 4229 PetscInt o = points[p+1]; 4230 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4231 updatePointBC_private(section, points[p], dof, add, o, perm, values, off, array); 4232 } break; 4233 default: 4234 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4235 } 4236 } 4237 /* Cleanup points */ 4238 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4239 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4240 /* Cleanup array */ 4241 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4242 PetscFunctionReturn(0); 4243 } 4244 4245 #undef __FUNCT__ 4246 #define __FUNCT__ "DMPlexVecSetFieldClosure_Internal" 4247 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, const PetscScalar values[], InsertMode mode) 4248 { 4249 PetscSection clSection; 4250 IS clPoints; 4251 PetscScalar *array; 4252 PetscInt *points = NULL; 4253 const PetscInt *clp, *perm; 4254 PetscInt numFields, numPoints, p; 4255 PetscInt offset = 0, fcomp, f; 4256 PetscErrorCode ierr; 4257 4258 PetscFunctionBeginHot; 4259 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4260 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4261 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4262 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4263 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4264 /* Get points */ 4265 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4266 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4267 if (!clPoints) { 4268 PetscInt pStart, pEnd, q; 4269 4270 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4271 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4272 /* Compress out points not in the section */ 4273 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4274 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4275 points[q*2] = points[p]; 4276 points[q*2+1] = points[p+1]; 4277 ++q; 4278 } 4279 } 4280 numPoints = q; 4281 } else { 4282 PetscInt dof, off; 4283 4284 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4285 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4286 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4287 numPoints = dof/2; 4288 points = (PetscInt *) &clp[off]; 4289 } 4290 /* Get array */ 4291 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4292 /* Get values */ 4293 for (f = 0; f < numFields; ++f) { 4294 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4295 if (!fieldActive[f]) { 4296 for (p = 0; p < numPoints*2; p += 2) { 4297 PetscInt fdof; 4298 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4299 offset += fdof; 4300 } 4301 continue; 4302 } 4303 switch (mode) { 4304 case INSERT_VALUES: 4305 for (p = 0; p < numPoints*2; p += 2) { 4306 const PetscInt point = points[p]; 4307 const PetscInt o = points[p+1]; 4308 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, perm, values, &offset, array); 4309 } break; 4310 case INSERT_ALL_VALUES: 4311 for (p = 0; p < numPoints*2; p += 2) { 4312 const PetscInt point = points[p]; 4313 const PetscInt o = points[p+1]; 4314 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, perm, values, &offset, array); 4315 } break; 4316 case INSERT_BC_VALUES: 4317 for (p = 0; p < numPoints*2; p += 2) { 4318 const PetscInt point = points[p]; 4319 const PetscInt o = points[p+1]; 4320 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, perm, values, &offset, array); 4321 } break; 4322 case ADD_VALUES: 4323 for (p = 0; p < numPoints*2; p += 2) { 4324 const PetscInt point = points[p]; 4325 const PetscInt o = points[p+1]; 4326 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, perm, values, &offset, array); 4327 } break; 4328 case ADD_ALL_VALUES: 4329 for (p = 0; p < numPoints*2; p += 2) { 4330 const PetscInt point = points[p]; 4331 const PetscInt o = points[p+1]; 4332 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, perm, values, &offset, array); 4333 } break; 4334 default: 4335 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4336 } 4337 } 4338 /* Cleanup points */ 4339 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4340 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4341 /* Cleanup array */ 4342 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4343 PetscFunctionReturn(0); 4344 } 4345 4346 #undef __FUNCT__ 4347 #define __FUNCT__ "DMPlexPrintMatSetValues" 4348 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4349 { 4350 PetscMPIInt rank; 4351 PetscInt i, j; 4352 PetscErrorCode ierr; 4353 4354 PetscFunctionBegin; 4355 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4356 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 4357 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4358 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4359 numCIndices = numCIndices ? numCIndices : numRIndices; 4360 for (i = 0; i < numRIndices; i++) { 4361 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4362 for (j = 0; j < numCIndices; j++) { 4363 #if defined(PETSC_USE_COMPLEX) 4364 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4365 #else 4366 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4367 #endif 4368 } 4369 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4370 } 4371 PetscFunctionReturn(0); 4372 } 4373 4374 #undef __FUNCT__ 4375 #define __FUNCT__ "DMPlexGetIndicesPoint_Internal" 4376 /* . off - The global offset of this point */ 4377 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4378 { 4379 PetscInt dof; /* The number of unknowns on this point */ 4380 PetscInt cdof; /* The number of constraints on this point */ 4381 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4382 PetscInt cind = 0, k; 4383 PetscErrorCode ierr; 4384 4385 PetscFunctionBegin; 4386 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4387 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4388 if (!cdof || setBC) { 4389 if (orientation >= 0) { 4390 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 4391 } else { 4392 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 4393 } 4394 } else { 4395 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4396 if (orientation >= 0) { 4397 for (k = 0; k < dof; ++k) { 4398 if ((cind < cdof) && (k == cdofs[cind])) { 4399 /* Insert check for returning constrained indices */ 4400 indices[*loff+k] = -(off+k+1); 4401 ++cind; 4402 } else { 4403 indices[*loff+k] = off+k-cind; 4404 } 4405 } 4406 } else { 4407 for (k = 0; k < dof; ++k) { 4408 if ((cind < cdof) && (k == cdofs[cind])) { 4409 /* Insert check for returning constrained indices */ 4410 indices[*loff+dof-k-1] = -(off+k+1); 4411 ++cind; 4412 } else { 4413 indices[*loff+dof-k-1] = off+k-cind; 4414 } 4415 } 4416 } 4417 } 4418 *loff += dof; 4419 PetscFunctionReturn(0); 4420 } 4421 4422 #undef __FUNCT__ 4423 #define __FUNCT__ "DMPlexGetIndicesPointFields_Internal" 4424 /* . off - The global offset of this point */ 4425 PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4426 { 4427 PetscInt numFields, foff, f; 4428 PetscErrorCode ierr; 4429 4430 PetscFunctionBegin; 4431 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4432 for (f = 0, foff = 0; f < numFields; ++f) { 4433 PetscInt fdof, fcomp, cfdof; 4434 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4435 PetscInt cind = 0, k, c; 4436 4437 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4438 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4439 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4440 if (!cfdof || setBC) { 4441 if (orientation >= 0) { 4442 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 4443 } else { 4444 for (k = fdof/fcomp-1; k >= 0; --k) { 4445 for (c = 0; c < fcomp; ++c) { 4446 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 4447 } 4448 } 4449 } 4450 } else { 4451 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4452 if (orientation >= 0) { 4453 for (k = 0; k < fdof; ++k) { 4454 if ((cind < cfdof) && (k == fcdofs[cind])) { 4455 indices[foffs[f]+k] = -(off+foff+k+1); 4456 ++cind; 4457 } else { 4458 indices[foffs[f]+k] = off+foff+k-cind; 4459 } 4460 } 4461 } else { 4462 for (k = fdof/fcomp-1; k >= 0; --k) { 4463 for (c = 0; c < fcomp; ++c) { 4464 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 4465 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 4466 ++cind; 4467 } else { 4468 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 4469 } 4470 } 4471 } 4472 } 4473 } 4474 foff += (setBC ? fdof : (fdof - cfdof)); 4475 foffs[f] += fdof; 4476 } 4477 PetscFunctionReturn(0); 4478 } 4479 4480 #undef __FUNCT__ 4481 #define __FUNCT__ "DMPlexAnchorsModifyMat" 4482 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) 4483 { 4484 Mat cMat; 4485 PetscSection aSec, cSec; 4486 IS aIS; 4487 PetscInt aStart = -1, aEnd = -1; 4488 const PetscInt *anchors; 4489 PetscInt numFields, f, p, q, newP = 0; 4490 PetscInt newNumPoints = 0, newNumIndices = 0; 4491 PetscInt *newPoints, *indices, *newIndices; 4492 PetscInt maxAnchor, maxDof; 4493 PetscInt newOffsets[32]; 4494 PetscInt *pointMatOffsets[32]; 4495 PetscInt *newPointOffsets[32]; 4496 PetscScalar *pointMat[32]; 4497 PetscScalar *newValues=NULL,*tmpValues; 4498 PetscBool anyConstrained = PETSC_FALSE; 4499 PetscErrorCode ierr; 4500 4501 PetscFunctionBegin; 4502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4503 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4504 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4505 4506 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4507 /* if there are point-to-point constraints */ 4508 if (aSec) { 4509 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4510 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 4511 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 4512 /* figure out how many points are going to be in the new element matrix 4513 * (we allow double counting, because it's all just going to be summed 4514 * into the global matrix anyway) */ 4515 for (p = 0; p < 2*numPoints; p+=2) { 4516 PetscInt b = points[p]; 4517 PetscInt bDof = 0, bSecDof; 4518 4519 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4520 if (!bSecDof) { 4521 continue; 4522 } 4523 if (b >= aStart && b < aEnd) { 4524 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4525 } 4526 if (bDof) { 4527 /* this point is constrained */ 4528 /* it is going to be replaced by its anchors */ 4529 PetscInt bOff, q; 4530 4531 anyConstrained = PETSC_TRUE; 4532 newNumPoints += bDof; 4533 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4534 for (q = 0; q < bDof; q++) { 4535 PetscInt a = anchors[bOff + q]; 4536 PetscInt aDof; 4537 4538 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4539 newNumIndices += aDof; 4540 for (f = 0; f < numFields; ++f) { 4541 PetscInt fDof; 4542 4543 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4544 newOffsets[f+1] += fDof; 4545 } 4546 } 4547 } 4548 else { 4549 /* this point is not constrained */ 4550 newNumPoints++; 4551 newNumIndices += bSecDof; 4552 for (f = 0; f < numFields; ++f) { 4553 PetscInt fDof; 4554 4555 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4556 newOffsets[f+1] += fDof; 4557 } 4558 } 4559 } 4560 } 4561 if (!anyConstrained) { 4562 if (outNumPoints) *outNumPoints = 0; 4563 if (outNumIndices) *outNumIndices = 0; 4564 if (outPoints) *outPoints = NULL; 4565 if (outValues) *outValues = NULL; 4566 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4567 PetscFunctionReturn(0); 4568 } 4569 4570 if (outNumPoints) *outNumPoints = newNumPoints; 4571 if (outNumIndices) *outNumIndices = newNumIndices; 4572 4573 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4574 4575 if (!outPoints && !outValues) { 4576 if (offsets) { 4577 for (f = 0; f <= numFields; f++) { 4578 offsets[f] = newOffsets[f]; 4579 } 4580 } 4581 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4582 PetscFunctionReturn(0); 4583 } 4584 4585 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 4586 4587 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4588 4589 /* workspaces */ 4590 if (numFields) { 4591 for (f = 0; f < numFields; f++) { 4592 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4593 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4594 } 4595 } 4596 else { 4597 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4598 ierr = DMGetWorkArray(dm,numPoints,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4599 } 4600 4601 /* get workspaces for the point-to-point matrices */ 4602 if (numFields) { 4603 PetscInt totalOffset, totalMatOffset; 4604 4605 for (p = 0; p < numPoints; p++) { 4606 PetscInt b = points[2*p]; 4607 PetscInt bDof = 0, bSecDof; 4608 4609 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4610 if (!bSecDof) { 4611 for (f = 0; f < numFields; f++) { 4612 newPointOffsets[f][p + 1] = 0; 4613 pointMatOffsets[f][p + 1] = 0; 4614 } 4615 continue; 4616 } 4617 if (b >= aStart && b < aEnd) { 4618 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4619 } 4620 if (bDof) { 4621 for (f = 0; f < numFields; f++) { 4622 PetscInt fDof, q, bOff, allFDof = 0; 4623 4624 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4625 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4626 for (q = 0; q < bDof; q++) { 4627 PetscInt a = anchors[bOff + q]; 4628 PetscInt aFDof; 4629 4630 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4631 allFDof += aFDof; 4632 } 4633 newPointOffsets[f][p+1] = allFDof; 4634 pointMatOffsets[f][p+1] = fDof * allFDof; 4635 } 4636 } 4637 else { 4638 for (f = 0; f < numFields; f++) { 4639 PetscInt fDof; 4640 4641 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4642 newPointOffsets[f][p+1] = fDof; 4643 pointMatOffsets[f][p+1] = 0; 4644 } 4645 } 4646 } 4647 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 4648 newPointOffsets[f][0] = totalOffset; 4649 pointMatOffsets[f][0] = totalMatOffset; 4650 for (p = 0; p < numPoints; p++) { 4651 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 4652 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 4653 } 4654 totalOffset = newPointOffsets[f][numPoints]; 4655 totalMatOffset = pointMatOffsets[f][numPoints]; 4656 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4657 } 4658 } 4659 else { 4660 for (p = 0; p < numPoints; p++) { 4661 PetscInt b = points[2*p]; 4662 PetscInt bDof = 0, bSecDof; 4663 4664 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4665 if (!bSecDof) { 4666 newPointOffsets[0][p + 1] = 0; 4667 pointMatOffsets[0][p + 1] = 0; 4668 continue; 4669 } 4670 if (b >= aStart && b < aEnd) { 4671 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4672 } 4673 if (bDof) { 4674 PetscInt bOff, q, allDof = 0; 4675 4676 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4677 for (q = 0; q < bDof; q++) { 4678 PetscInt a = anchors[bOff + q], aDof; 4679 4680 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 4681 allDof += aDof; 4682 } 4683 newPointOffsets[0][p+1] = allDof; 4684 pointMatOffsets[0][p+1] = bSecDof * allDof; 4685 } 4686 else { 4687 newPointOffsets[0][p+1] = bSecDof; 4688 pointMatOffsets[0][p+1] = 0; 4689 } 4690 } 4691 newPointOffsets[0][0] = 0; 4692 pointMatOffsets[0][0] = 0; 4693 for (p = 0; p < numPoints; p++) { 4694 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 4695 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 4696 } 4697 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4698 } 4699 4700 /* output arrays */ 4701 ierr = DMGetWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4702 4703 /* get the point-to-point matrices; construct newPoints */ 4704 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 4705 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4706 ierr = DMGetWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4707 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4708 if (numFields) { 4709 for (p = 0, newP = 0; p < numPoints; p++) { 4710 PetscInt b = points[2*p]; 4711 PetscInt o = points[2*p+1]; 4712 PetscInt bDof = 0, bSecDof; 4713 4714 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 4715 if (!bSecDof) { 4716 continue; 4717 } 4718 if (b >= aStart && b < aEnd) { 4719 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4720 } 4721 if (bDof) { 4722 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 4723 4724 fStart[0] = 0; 4725 fEnd[0] = 0; 4726 for (f = 0; f < numFields; f++) { 4727 PetscInt fDof; 4728 4729 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 4730 fStart[f+1] = fStart[f] + fDof; 4731 fEnd[f+1] = fStart[f+1]; 4732 } 4733 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4734 ierr = DMPlexGetIndicesPointFields_Internal(cSec, b, bOff, fEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4735 4736 fAnchorStart[0] = 0; 4737 fAnchorEnd[0] = 0; 4738 for (f = 0; f < numFields; f++) { 4739 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 4740 4741 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 4742 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 4743 } 4744 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4745 for (q = 0; q < bDof; q++) { 4746 PetscInt a = anchors[bOff + q], aOff; 4747 4748 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4749 newPoints[2*(newP + q)] = a; 4750 newPoints[2*(newP + q) + 1] = 0; 4751 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4752 ierr = DMPlexGetIndicesPointFields_Internal(section, a, aOff, fAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4753 } 4754 newP += bDof; 4755 4756 if (outValues) { 4757 /* get the point-to-point submatrix */ 4758 for (f = 0; f < numFields; f++) { 4759 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 4760 } 4761 } 4762 } 4763 else { 4764 newPoints[2 * newP] = b; 4765 newPoints[2 * newP + 1] = o; 4766 newP++; 4767 } 4768 } 4769 } else { 4770 for (p = 0; p < numPoints; p++) { 4771 PetscInt b = points[2*p]; 4772 PetscInt o = points[2*p+1]; 4773 PetscInt bDof = 0, bSecDof; 4774 4775 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 4776 if (!bSecDof) { 4777 continue; 4778 } 4779 if (b >= aStart && b < aEnd) { 4780 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4781 } 4782 if (bDof) { 4783 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 4784 4785 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4786 ierr = DMPlexGetIndicesPoint_Internal(cSec, b, bOff, &bEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4787 4788 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4789 for (q = 0; q < bDof; q++) { 4790 PetscInt a = anchors[bOff + q], aOff; 4791 4792 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4793 4794 newPoints[2*(newP + q)] = a; 4795 newPoints[2*(newP + q) + 1] = 0; 4796 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4797 ierr = DMPlexGetIndicesPoint_Internal(section, a, aOff, &bAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4798 } 4799 newP += bDof; 4800 4801 /* get the point-to-point submatrix */ 4802 if (outValues) { 4803 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 4804 } 4805 } 4806 else { 4807 newPoints[2 * newP] = b; 4808 newPoints[2 * newP + 1] = o; 4809 newP++; 4810 } 4811 } 4812 } 4813 4814 if (outValues) { 4815 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4816 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 4817 /* multiply constraints on the right */ 4818 if (numFields) { 4819 for (f = 0; f < numFields; f++) { 4820 PetscInt oldOff = offsets[f]; 4821 4822 for (p = 0; p < numPoints; p++) { 4823 PetscInt cStart = newPointOffsets[f][p]; 4824 PetscInt b = points[2 * p]; 4825 PetscInt c, r, k; 4826 PetscInt dof; 4827 4828 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4829 if (!dof) { 4830 continue; 4831 } 4832 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4833 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 4834 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 4835 4836 for (r = 0; r < numIndices; r++) { 4837 for (c = 0; c < nCols; c++) { 4838 for (k = 0; k < dof; k++) { 4839 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4840 } 4841 } 4842 } 4843 } 4844 else { 4845 /* copy this column as is */ 4846 for (r = 0; r < numIndices; r++) { 4847 for (c = 0; c < dof; c++) { 4848 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4849 } 4850 } 4851 } 4852 oldOff += dof; 4853 } 4854 } 4855 } 4856 else { 4857 PetscInt oldOff = 0; 4858 for (p = 0; p < numPoints; p++) { 4859 PetscInt cStart = newPointOffsets[0][p]; 4860 PetscInt b = points[2 * p]; 4861 PetscInt c, r, k; 4862 PetscInt dof; 4863 4864 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4865 if (!dof) { 4866 continue; 4867 } 4868 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4869 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 4870 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 4871 4872 for (r = 0; r < numIndices; r++) { 4873 for (c = 0; c < nCols; c++) { 4874 for (k = 0; k < dof; k++) { 4875 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4876 } 4877 } 4878 } 4879 } 4880 else { 4881 /* copy this column as is */ 4882 for (r = 0; r < numIndices; r++) { 4883 for (c = 0; c < dof; c++) { 4884 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4885 } 4886 } 4887 } 4888 oldOff += dof; 4889 } 4890 } 4891 4892 if (multiplyLeft) { 4893 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4894 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 4895 /* multiply constraints transpose on the left */ 4896 if (numFields) { 4897 for (f = 0; f < numFields; f++) { 4898 PetscInt oldOff = offsets[f]; 4899 4900 for (p = 0; p < numPoints; p++) { 4901 PetscInt rStart = newPointOffsets[f][p]; 4902 PetscInt b = points[2 * p]; 4903 PetscInt c, r, k; 4904 PetscInt dof; 4905 4906 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4907 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4908 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 4909 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 4910 4911 for (r = 0; r < nRows; r++) { 4912 for (c = 0; c < newNumIndices; c++) { 4913 for (k = 0; k < dof; k++) { 4914 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4915 } 4916 } 4917 } 4918 } 4919 else { 4920 /* copy this row as is */ 4921 for (r = 0; r < dof; r++) { 4922 for (c = 0; c < newNumIndices; c++) { 4923 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4924 } 4925 } 4926 } 4927 oldOff += dof; 4928 } 4929 } 4930 } 4931 else { 4932 PetscInt oldOff = 0; 4933 4934 for (p = 0; p < numPoints; p++) { 4935 PetscInt rStart = newPointOffsets[0][p]; 4936 PetscInt b = points[2 * p]; 4937 PetscInt c, r, k; 4938 PetscInt dof; 4939 4940 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4941 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4942 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 4943 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 4944 4945 for (r = 0; r < nRows; r++) { 4946 for (c = 0; c < newNumIndices; c++) { 4947 for (k = 0; k < dof; k++) { 4948 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4949 } 4950 } 4951 } 4952 } 4953 else { 4954 /* copy this row as is */ 4955 for (r = 0; r < dof; r++) { 4956 for (c = 0; c < newNumIndices; c++) { 4957 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4958 } 4959 } 4960 } 4961 oldOff += dof; 4962 } 4963 } 4964 4965 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4966 } 4967 else { 4968 newValues = tmpValues; 4969 } 4970 } 4971 4972 /* clean up */ 4973 ierr = DMRestoreWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4974 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4975 4976 if (numFields) { 4977 for (f = 0; f < numFields; f++) { 4978 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4979 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4980 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4981 } 4982 } 4983 else { 4984 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4985 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4986 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4987 } 4988 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4989 4990 /* output */ 4991 if (outPoints) { 4992 *outPoints = newPoints; 4993 } 4994 else { 4995 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4996 } 4997 if (outValues) { 4998 *outValues = newValues; 4999 } 5000 for (f = 0; f <= numFields; f++) { 5001 offsets[f] = newOffsets[f]; 5002 } 5003 PetscFunctionReturn(0); 5004 } 5005 5006 #undef __FUNCT__ 5007 #define __FUNCT__ "DMPlexGetClosureIndices" 5008 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 5009 { 5010 PetscSection clSection; 5011 IS clPoints; 5012 const PetscInt *clp; 5013 PetscInt *points = NULL, *pointsNew; 5014 PetscInt numPoints, numPointsNew; 5015 PetscInt offsets[32]; 5016 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 5017 PetscErrorCode ierr; 5018 5019 PetscFunctionBegin; 5020 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5021 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5022 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5023 if (numIndices) PetscValidPointer(numIndices, 4); 5024 PetscValidPointer(indices, 5); 5025 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5026 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 5027 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5028 /* Get points in closure */ 5029 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 5030 if (!clPoints) { 5031 PetscInt pStart, pEnd, q; 5032 5033 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5034 /* Compress out points not in the section */ 5035 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5036 for (p = 0, q = 0; p < numPoints*2; p += 2) { 5037 if ((points[p] >= pStart) && (points[p] < pEnd)) { 5038 points[q*2] = points[p]; 5039 points[q*2+1] = points[p+1]; 5040 ++q; 5041 } 5042 } 5043 numPoints = q; 5044 } else { 5045 PetscInt dof, off; 5046 5047 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 5048 numPoints = dof/2; 5049 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 5050 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 5051 points = (PetscInt *) &clp[off]; 5052 } 5053 /* Get number of indices and indices per field */ 5054 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 5055 PetscInt dof, fdof; 5056 5057 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5058 for (f = 0; f < Nf; ++f) { 5059 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5060 offsets[f+1] += fdof; 5061 } 5062 Nind += dof; 5063 } 5064 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 5065 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[Nf], Nind); 5066 /* Correct for hanging node constraints */ 5067 { 5068 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 5069 if (numPointsNew) { 5070 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 5071 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 5072 numPoints = numPointsNew; 5073 Nind = NindNew; 5074 points = pointsNew; 5075 } 5076 } 5077 /* Calculate indices */ 5078 ierr = DMGetWorkArray(dm, Nind, PETSC_INT, indices);CHKERRQ(ierr); 5079 if (Nf) { 5080 if (outOffsets) { 5081 PetscInt f; 5082 5083 for (f = 0; f <= Nf; f++) { 5084 outOffsets[f] = offsets[f]; 5085 } 5086 } 5087 for (p = 0; p < numPoints*2; p += 2) { 5088 PetscInt o = points[p+1]; 5089 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5090 DMPlexGetIndicesPointFields_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, *indices); 5091 } 5092 } else { 5093 for (p = 0, off = 0; p < numPoints*2; p += 2) { 5094 PetscInt o = points[p+1]; 5095 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5096 DMPlexGetIndicesPoint_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, *indices); 5097 } 5098 } 5099 /* Cleanup points */ 5100 if (numPointsNew) { 5101 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, PETSC_INT, &pointsNew);CHKERRQ(ierr); 5102 } else { 5103 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 5104 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 5105 } 5106 if (numIndices) *numIndices = Nind; 5107 PetscFunctionReturn(0); 5108 } 5109 5110 #undef __FUNCT__ 5111 #define __FUNCT__ "DMPlexRestoreClosureIndices" 5112 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 5113 { 5114 PetscErrorCode ierr; 5115 5116 PetscFunctionBegin; 5117 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5118 PetscValidPointer(indices, 5); 5119 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, indices);CHKERRQ(ierr); 5120 PetscFunctionReturn(0); 5121 } 5122 5123 #undef __FUNCT__ 5124 #define __FUNCT__ "DMPlexMatSetClosure" 5125 /*@C 5126 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 5127 5128 Not collective 5129 5130 Input Parameters: 5131 + dm - The DM 5132 . section - The section describing the layout in v, or NULL to use the default section 5133 . globalSection - The section describing the layout in v, or NULL to use the default global section 5134 . A - The matrix 5135 . point - The sieve point in the DM 5136 . values - The array of values 5137 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 5138 5139 Fortran Notes: 5140 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5141 5142 Level: intermediate 5143 5144 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 5145 @*/ 5146 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5147 { 5148 DM_Plex *mesh = (DM_Plex*) dm->data; 5149 PetscSection clSection; 5150 IS clPoints; 5151 PetscInt *points = NULL, *newPoints; 5152 const PetscInt *clp; 5153 PetscInt *indices; 5154 PetscInt offsets[32]; 5155 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 5156 PetscScalar *newValues; 5157 PetscErrorCode ierr; 5158 5159 PetscFunctionBegin; 5160 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5161 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 5162 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5163 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 5164 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5165 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 5166 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5167 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5168 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5169 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 5170 if (!clPoints) { 5171 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5172 /* Compress out points not in the section */ 5173 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5174 for (p = 0, q = 0; p < numPoints*2; p += 2) { 5175 if ((points[p] >= pStart) && (points[p] < pEnd)) { 5176 points[q*2] = points[p]; 5177 points[q*2+1] = points[p+1]; 5178 ++q; 5179 } 5180 } 5181 numPoints = q; 5182 } else { 5183 PetscInt dof, off; 5184 5185 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 5186 numPoints = dof/2; 5187 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 5188 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 5189 points = (PetscInt *) &clp[off]; 5190 } 5191 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 5192 PetscInt fdof; 5193 5194 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5195 for (f = 0; f < numFields; ++f) { 5196 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5197 offsets[f+1] += fdof; 5198 } 5199 numIndices += dof; 5200 } 5201 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 5202 5203 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 5204 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 5205 if (newNumPoints) { 5206 if (!clPoints) { 5207 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5208 } else { 5209 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 5210 } 5211 numPoints = newNumPoints; 5212 numIndices = newNumIndices; 5213 points = newPoints; 5214 values = newValues; 5215 } 5216 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 5217 if (numFields) { 5218 for (p = 0; p < numPoints*2; p += 2) { 5219 PetscInt o = points[p+1]; 5220 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5221 DMPlexGetIndicesPointFields_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 5222 } 5223 } else { 5224 for (p = 0, off = 0; p < numPoints*2; p += 2) { 5225 PetscInt o = points[p+1]; 5226 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 5227 DMPlexGetIndicesPoint_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 5228 } 5229 } 5230 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 5231 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 5232 if (mesh->printFEM > 1) { 5233 PetscInt i; 5234 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 5235 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %d", indices[i]);CHKERRQ(ierr);} 5236 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5237 } 5238 if (ierr) { 5239 PetscMPIInt rank; 5240 PetscErrorCode ierr2; 5241 5242 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5243 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5244 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 5245 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 5246 CHKERRQ(ierr); 5247 } 5248 if (newNumPoints) { 5249 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 5250 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 5251 } 5252 else { 5253 if (!clPoints) { 5254 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5255 } else { 5256 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 5257 } 5258 } 5259 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 5260 PetscFunctionReturn(0); 5261 } 5262 5263 #undef __FUNCT__ 5264 #define __FUNCT__ "DMPlexMatSetClosureRefined" 5265 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5266 { 5267 DM_Plex *mesh = (DM_Plex*) dmf->data; 5268 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5269 PetscInt *cpoints = NULL; 5270 PetscInt *findices, *cindices; 5271 PetscInt foffsets[32], coffsets[32]; 5272 CellRefiner cellRefiner; 5273 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5274 PetscErrorCode ierr; 5275 5276 PetscFunctionBegin; 5277 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5278 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5279 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5280 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5281 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5282 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5283 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5284 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5285 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5286 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5287 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 5288 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5289 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5290 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5291 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5292 /* Column indices */ 5293 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5294 maxFPoints = numCPoints; 5295 /* Compress out points not in the section */ 5296 /* TODO: Squeeze out points with 0 dof as well */ 5297 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5298 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5299 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5300 cpoints[q*2] = cpoints[p]; 5301 cpoints[q*2+1] = cpoints[p+1]; 5302 ++q; 5303 } 5304 } 5305 numCPoints = q; 5306 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5307 PetscInt fdof; 5308 5309 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5310 if (!dof) continue; 5311 for (f = 0; f < numFields; ++f) { 5312 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5313 coffsets[f+1] += fdof; 5314 } 5315 numCIndices += dof; 5316 } 5317 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5318 /* Row indices */ 5319 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5320 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5321 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5322 for (r = 0, q = 0; r < numSubcells; ++r) { 5323 /* TODO Map from coarse to fine cells */ 5324 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5325 /* Compress out points not in the section */ 5326 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5327 for (p = 0; p < numFPoints*2; p += 2) { 5328 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5329 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5330 if (!dof) continue; 5331 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5332 if (s < q) continue; 5333 ftotpoints[q*2] = fpoints[p]; 5334 ftotpoints[q*2+1] = fpoints[p+1]; 5335 ++q; 5336 } 5337 } 5338 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5339 } 5340 numFPoints = q; 5341 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5342 PetscInt fdof; 5343 5344 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5345 if (!dof) continue; 5346 for (f = 0; f < numFields; ++f) { 5347 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5348 foffsets[f+1] += fdof; 5349 } 5350 numFIndices += dof; 5351 } 5352 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5353 5354 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5355 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5356 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5357 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5358 if (numFields) { 5359 for (p = 0; p < numFPoints*2; p += 2) { 5360 PetscInt o = ftotpoints[p+1]; 5361 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5362 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5363 } 5364 for (p = 0; p < numCPoints*2; p += 2) { 5365 PetscInt o = cpoints[p+1]; 5366 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5367 DMPlexGetIndicesPointFields_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5368 } 5369 } else { 5370 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5371 PetscInt o = ftotpoints[p+1]; 5372 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5373 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5374 } 5375 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5376 PetscInt o = cpoints[p+1]; 5377 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5378 DMPlexGetIndicesPoint_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5379 } 5380 } 5381 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5382 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5383 if (ierr) { 5384 PetscMPIInt rank; 5385 PetscErrorCode ierr2; 5386 5387 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5388 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5389 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5390 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 5391 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 5392 CHKERRQ(ierr); 5393 } 5394 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5395 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5396 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5397 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5398 PetscFunctionReturn(0); 5399 } 5400 5401 #undef __FUNCT__ 5402 #define __FUNCT__ "DMPlexMatGetClosureIndicesRefined" 5403 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5404 { 5405 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5406 PetscInt *cpoints = NULL; 5407 PetscInt foffsets[32], coffsets[32]; 5408 CellRefiner cellRefiner; 5409 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5410 PetscErrorCode ierr; 5411 5412 PetscFunctionBegin; 5413 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5414 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5415 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5416 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5417 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5418 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5419 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5420 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5421 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5422 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5423 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5424 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5425 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5426 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5427 /* Column indices */ 5428 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5429 maxFPoints = numCPoints; 5430 /* Compress out points not in the section */ 5431 /* TODO: Squeeze out points with 0 dof as well */ 5432 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5433 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5434 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5435 cpoints[q*2] = cpoints[p]; 5436 cpoints[q*2+1] = cpoints[p+1]; 5437 ++q; 5438 } 5439 } 5440 numCPoints = q; 5441 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5442 PetscInt fdof; 5443 5444 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5445 if (!dof) continue; 5446 for (f = 0; f < numFields; ++f) { 5447 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5448 coffsets[f+1] += fdof; 5449 } 5450 numCIndices += dof; 5451 } 5452 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5453 /* Row indices */ 5454 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5455 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5456 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5457 for (r = 0, q = 0; r < numSubcells; ++r) { 5458 /* TODO Map from coarse to fine cells */ 5459 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5460 /* Compress out points not in the section */ 5461 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5462 for (p = 0; p < numFPoints*2; p += 2) { 5463 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5464 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5465 if (!dof) continue; 5466 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5467 if (s < q) continue; 5468 ftotpoints[q*2] = fpoints[p]; 5469 ftotpoints[q*2+1] = fpoints[p+1]; 5470 ++q; 5471 } 5472 } 5473 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5474 } 5475 numFPoints = q; 5476 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5477 PetscInt fdof; 5478 5479 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5480 if (!dof) continue; 5481 for (f = 0; f < numFields; ++f) { 5482 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5483 foffsets[f+1] += fdof; 5484 } 5485 numFIndices += dof; 5486 } 5487 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5488 5489 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5490 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5491 if (numFields) { 5492 for (p = 0; p < numFPoints*2; p += 2) { 5493 PetscInt o = ftotpoints[p+1]; 5494 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5495 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5496 } 5497 for (p = 0; p < numCPoints*2; p += 2) { 5498 PetscInt o = cpoints[p+1]; 5499 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5500 DMPlexGetIndicesPointFields_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5501 } 5502 } else { 5503 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5504 PetscInt o = ftotpoints[p+1]; 5505 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5506 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5507 } 5508 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5509 PetscInt o = cpoints[p+1]; 5510 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5511 DMPlexGetIndicesPoint_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5512 } 5513 } 5514 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5515 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5516 PetscFunctionReturn(0); 5517 } 5518 5519 #undef __FUNCT__ 5520 #define __FUNCT__ "DMPlexGetHybridBounds" 5521 /*@ 5522 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5523 5524 Input Parameter: 5525 . dm - The DMPlex object 5526 5527 Output Parameters: 5528 + cMax - The first hybrid cell 5529 . fMax - The first hybrid face 5530 . eMax - The first hybrid edge 5531 - vMax - The first hybrid vertex 5532 5533 Level: developer 5534 5535 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 5536 @*/ 5537 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5538 { 5539 DM_Plex *mesh = (DM_Plex*) dm->data; 5540 PetscInt dim; 5541 PetscErrorCode ierr; 5542 5543 PetscFunctionBegin; 5544 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5545 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5546 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5547 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5548 if (eMax) *eMax = mesh->hybridPointMax[1]; 5549 if (vMax) *vMax = mesh->hybridPointMax[0]; 5550 PetscFunctionReturn(0); 5551 } 5552 5553 #undef __FUNCT__ 5554 #define __FUNCT__ "DMPlexSetHybridBounds" 5555 /*@ 5556 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 5557 5558 Input Parameters: 5559 . dm - The DMPlex object 5560 . cMax - The first hybrid cell 5561 . fMax - The first hybrid face 5562 . eMax - The first hybrid edge 5563 - vMax - The first hybrid vertex 5564 5565 Level: developer 5566 5567 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 5568 @*/ 5569 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 5570 { 5571 DM_Plex *mesh = (DM_Plex*) dm->data; 5572 PetscInt dim; 5573 PetscErrorCode ierr; 5574 5575 PetscFunctionBegin; 5576 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5577 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5578 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 5579 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 5580 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 5581 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 5582 PetscFunctionReturn(0); 5583 } 5584 5585 #undef __FUNCT__ 5586 #define __FUNCT__ "DMPlexGetVTKCellHeight" 5587 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 5588 { 5589 DM_Plex *mesh = (DM_Plex*) dm->data; 5590 5591 PetscFunctionBegin; 5592 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5593 PetscValidPointer(cellHeight, 2); 5594 *cellHeight = mesh->vtkCellHeight; 5595 PetscFunctionReturn(0); 5596 } 5597 5598 #undef __FUNCT__ 5599 #define __FUNCT__ "DMPlexSetVTKCellHeight" 5600 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 5601 { 5602 DM_Plex *mesh = (DM_Plex*) dm->data; 5603 5604 PetscFunctionBegin; 5605 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5606 mesh->vtkCellHeight = cellHeight; 5607 PetscFunctionReturn(0); 5608 } 5609 5610 #undef __FUNCT__ 5611 #define __FUNCT__ "DMPlexCreateNumbering_Private" 5612 /* We can easily have a form that takes an IS instead */ 5613 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 5614 { 5615 PetscSection section, globalSection; 5616 PetscInt *numbers, p; 5617 PetscErrorCode ierr; 5618 5619 PetscFunctionBegin; 5620 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5621 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 5622 for (p = pStart; p < pEnd; ++p) { 5623 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 5624 } 5625 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 5626 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 5627 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 5628 for (p = pStart; p < pEnd; ++p) { 5629 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 5630 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 5631 else numbers[p-pStart] += shift; 5632 } 5633 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 5634 if (globalSize) { 5635 PetscLayout layout; 5636 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 5637 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 5638 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 5639 } 5640 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5641 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 5642 PetscFunctionReturn(0); 5643 } 5644 5645 #undef __FUNCT__ 5646 #define __FUNCT__ "DMPlexCreateCellNumbering_Internal" 5647 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 5648 { 5649 PetscInt cellHeight, cStart, cEnd, cMax; 5650 PetscErrorCode ierr; 5651 5652 PetscFunctionBegin; 5653 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 5654 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5655 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5656 if (cMax >= 0 && !includeHybrid) cEnd = PetscMin(cEnd, cMax); 5657 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 5658 PetscFunctionReturn(0); 5659 } 5660 5661 #undef __FUNCT__ 5662 #define __FUNCT__ "DMPlexGetCellNumbering" 5663 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 5664 { 5665 DM_Plex *mesh = (DM_Plex*) dm->data; 5666 PetscErrorCode ierr; 5667 5668 PetscFunctionBegin; 5669 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5670 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 5671 *globalCellNumbers = mesh->globalCellNumbers; 5672 PetscFunctionReturn(0); 5673 } 5674 5675 #undef __FUNCT__ 5676 #define __FUNCT__ "DMPlexCreateVertexNumbering_Internal" 5677 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 5678 { 5679 PetscInt vStart, vEnd, vMax; 5680 PetscErrorCode ierr; 5681 5682 PetscFunctionBegin; 5683 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5684 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5685 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 5686 if (vMax >= 0 && !includeHybrid) vEnd = PetscMin(vEnd, vMax); 5687 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 5688 PetscFunctionReturn(0); 5689 } 5690 5691 #undef __FUNCT__ 5692 #define __FUNCT__ "DMPlexGetVertexNumbering" 5693 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 5694 { 5695 DM_Plex *mesh = (DM_Plex*) dm->data; 5696 PetscErrorCode ierr; 5697 5698 PetscFunctionBegin; 5699 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5700 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 5701 *globalVertexNumbers = mesh->globalVertexNumbers; 5702 PetscFunctionReturn(0); 5703 } 5704 5705 #undef __FUNCT__ 5706 #define __FUNCT__ "DMPlexCreatePointNumbering" 5707 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 5708 { 5709 IS nums[4]; 5710 PetscInt depths[4]; 5711 PetscInt depth, d, shift = 0; 5712 PetscErrorCode ierr; 5713 5714 PetscFunctionBegin; 5715 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5716 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5717 /* For unstratified meshes use dim instead of depth */ 5718 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 5719 depths[0] = depth; depths[1] = 0; 5720 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 5721 for (d = 0; d <= depth; ++d) { 5722 PetscInt pStart, pEnd, gsize; 5723 5724 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 5725 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 5726 shift += gsize; 5727 } 5728 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 5729 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 5730 PetscFunctionReturn(0); 5731 } 5732 5733 #undef __FUNCT__ 5734 #define __FUNCT__ "DMPlexCheckSymmetry" 5735 /*@ 5736 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5737 5738 Input Parameters: 5739 + dm - The DMPlex object 5740 5741 Note: This is a useful diagnostic when creating meshes programmatically. 5742 5743 Level: developer 5744 5745 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5746 @*/ 5747 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5748 { 5749 PetscSection coneSection, supportSection; 5750 const PetscInt *cone, *support; 5751 PetscInt coneSize, c, supportSize, s; 5752 PetscInt pStart, pEnd, p, csize, ssize; 5753 PetscErrorCode ierr; 5754 5755 PetscFunctionBegin; 5756 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5757 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5758 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5759 /* Check that point p is found in the support of its cone points, and vice versa */ 5760 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5761 for (p = pStart; p < pEnd; ++p) { 5762 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5763 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5764 for (c = 0; c < coneSize; ++c) { 5765 PetscBool dup = PETSC_FALSE; 5766 PetscInt d; 5767 for (d = c-1; d >= 0; --d) { 5768 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5769 } 5770 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5771 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5772 for (s = 0; s < supportSize; ++s) { 5773 if (support[s] == p) break; 5774 } 5775 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5776 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p);CHKERRQ(ierr); 5777 for (s = 0; s < coneSize; ++s) { 5778 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]);CHKERRQ(ierr); 5779 } 5780 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5781 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]);CHKERRQ(ierr); 5782 for (s = 0; s < supportSize; ++s) { 5783 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]);CHKERRQ(ierr); 5784 } 5785 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5786 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5787 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5788 } 5789 } 5790 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5791 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5792 for (s = 0; s < supportSize; ++s) { 5793 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5794 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5795 for (c = 0; c < coneSize; ++c) { 5796 if (cone[c] == p) break; 5797 } 5798 if (c >= coneSize) { 5799 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p);CHKERRQ(ierr); 5800 for (c = 0; c < supportSize; ++c) { 5801 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]);CHKERRQ(ierr); 5802 } 5803 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5804 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]);CHKERRQ(ierr); 5805 for (c = 0; c < coneSize; ++c) { 5806 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]);CHKERRQ(ierr); 5807 } 5808 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5809 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5810 } 5811 } 5812 } 5813 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5814 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5815 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5816 PetscFunctionReturn(0); 5817 } 5818 5819 #undef __FUNCT__ 5820 #define __FUNCT__ "DMPlexCheckSkeleton" 5821 /*@ 5822 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5823 5824 Input Parameters: 5825 + dm - The DMPlex object 5826 . isSimplex - Are the cells simplices or tensor products 5827 - cellHeight - Normally 0 5828 5829 Note: This is a useful diagnostic when creating meshes programmatically. 5830 5831 Level: developer 5832 5833 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5834 @*/ 5835 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5836 { 5837 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5838 PetscErrorCode ierr; 5839 5840 PetscFunctionBegin; 5841 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5842 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5843 switch (dim) { 5844 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5845 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5846 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5847 default: 5848 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5849 } 5850 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5851 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5852 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5853 cMax = cMax >= 0 ? cMax : cEnd; 5854 for (c = cStart; c < cMax; ++c) { 5855 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5856 5857 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5858 for (cl = 0; cl < closureSize*2; cl += 2) { 5859 const PetscInt p = closure[cl]; 5860 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5861 } 5862 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5863 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5864 } 5865 for (c = cMax; c < cEnd; ++c) { 5866 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5867 5868 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5869 for (cl = 0; cl < closureSize*2; cl += 2) { 5870 const PetscInt p = closure[cl]; 5871 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5872 } 5873 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5874 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5875 } 5876 PetscFunctionReturn(0); 5877 } 5878 5879 #undef __FUNCT__ 5880 #define __FUNCT__ "DMPlexCheckFaces" 5881 /*@ 5882 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5883 5884 Input Parameters: 5885 + dm - The DMPlex object 5886 . isSimplex - Are the cells simplices or tensor products 5887 - cellHeight - Normally 0 5888 5889 Note: This is a useful diagnostic when creating meshes programmatically. 5890 5891 Level: developer 5892 5893 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5894 @*/ 5895 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5896 { 5897 PetscInt pMax[4]; 5898 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5899 PetscErrorCode ierr; 5900 5901 PetscFunctionBegin; 5902 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5903 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5904 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5905 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5906 for (h = cellHeight; h < dim; ++h) { 5907 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5908 for (c = cStart; c < cEnd; ++c) { 5909 const PetscInt *cone, *ornt, *faces; 5910 PetscInt numFaces, faceSize, coneSize,f; 5911 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5912 5913 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5914 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5915 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5916 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5917 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5918 for (cl = 0; cl < closureSize*2; cl += 2) { 5919 const PetscInt p = closure[cl]; 5920 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5921 } 5922 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5923 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5924 for (f = 0; f < numFaces; ++f) { 5925 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5926 5927 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5928 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5929 const PetscInt p = fclosure[cl]; 5930 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5931 } 5932 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); 5933 for (v = 0; v < fnumCorners; ++v) { 5934 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]); 5935 } 5936 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5937 } 5938 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5939 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5940 } 5941 } 5942 PetscFunctionReturn(0); 5943 } 5944 5945 #undef __FUNCT__ 5946 #define __FUNCT__ "DMCreateInterpolation_Plex" 5947 /* Pointwise interpolation 5948 Just code FEM for now 5949 u^f = I u^c 5950 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5951 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5952 I_{ij} = psi^f_i phi^c_j 5953 */ 5954 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5955 { 5956 PetscSection gsc, gsf; 5957 PetscInt m, n; 5958 void *ctx; 5959 DM cdm; 5960 PetscBool regular; 5961 PetscErrorCode ierr; 5962 5963 PetscFunctionBegin; 5964 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5965 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5966 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5967 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5968 5969 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5970 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5971 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5972 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5973 5974 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 5975 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 5976 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5977 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5978 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 5979 /* Use naive scaling */ 5980 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5981 PetscFunctionReturn(0); 5982 } 5983 5984 #undef __FUNCT__ 5985 #define __FUNCT__ "DMCreateInjection_Plex" 5986 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 5987 { 5988 PetscErrorCode ierr; 5989 VecScatter ctx; 5990 5991 PetscFunctionBegin; 5992 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 5993 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 5994 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 5995 PetscFunctionReturn(0); 5996 } 5997 5998 #undef __FUNCT__ 5999 #define __FUNCT__ "DMCreateDefaultSection_Plex" 6000 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 6001 { 6002 PetscSection section; 6003 IS *bcPoints, *bcComps; 6004 PetscBool *isFE; 6005 PetscInt *bcFields, *numComp, *numDof; 6006 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 6007 PetscInt cStart, cEnd, cEndInterior; 6008 PetscErrorCode ierr; 6009 6010 PetscFunctionBegin; 6011 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 6012 if (!numFields) PetscFunctionReturn(0); 6013 /* FE and FV boundary conditions are handled slightly differently */ 6014 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 6015 for (f = 0; f < numFields; ++f) { 6016 PetscObject obj; 6017 PetscClassId id; 6018 6019 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 6020 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 6021 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 6022 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 6023 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 6024 } 6025 /* Allocate boundary point storage for FEM boundaries */ 6026 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6027 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6028 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6029 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 6030 ierr = PetscDSGetNumBoundary(dm->prob, &numBd);CHKERRQ(ierr); 6031 for (bd = 0; bd < numBd; ++bd) { 6032 PetscInt field; 6033 PetscBool isEssential; 6034 const char *labelName; 6035 DMLabel label; 6036 6037 ierr = PetscDSGetBoundary(dm->prob, bd, &isEssential, NULL, &labelName, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6038 ierr = DMGetLabel(dm,labelName,&label);CHKERRQ(ierr); 6039 if (label && isFE[field] && isEssential) ++numBC; 6040 } 6041 /* Add ghost cell boundaries for FVM */ 6042 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 6043 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 6044 /* Constrain ghost cells for FV */ 6045 for (f = 0; f < numFields; ++f) { 6046 PetscInt *newidx, c; 6047 6048 if (isFE[f] || cEndInterior < 0) continue; 6049 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 6050 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 6051 bcFields[bc] = f; 6052 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 6053 } 6054 /* Handle FEM Dirichlet boundaries */ 6055 for (bd = 0; bd < numBd; ++bd) { 6056 const char *bdLabel; 6057 DMLabel label; 6058 const PetscInt *comps; 6059 const PetscInt *values; 6060 PetscInt bd2, field, numComps, numValues; 6061 PetscBool isEssential, duplicate = PETSC_FALSE; 6062 6063 ierr = PetscDSGetBoundary(dm->prob, bd, &isEssential, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 6064 ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 6065 if (!isFE[field] || !label) continue; 6066 /* Only want to modify label once */ 6067 for (bd2 = 0; bd2 < bd; ++bd2) { 6068 const char *bdname; 6069 ierr = PetscDSGetBoundary(dm->prob, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6070 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 6071 if (duplicate) break; 6072 } 6073 if (!duplicate && (isFE[field])) { 6074 /* don't complete cells, which are just present to give orientation to the boundary */ 6075 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 6076 } 6077 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 6078 if (isEssential) { 6079 PetscInt *newidx; 6080 PetscInt n, newn = 0, p, v; 6081 6082 bcFields[bc] = field; 6083 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 6084 for (v = 0; v < numValues; ++v) { 6085 IS tmp; 6086 const PetscInt *idx; 6087 6088 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6089 if (!tmp) continue; 6090 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6091 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6092 if (isFE[field]) { 6093 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 6094 } else { 6095 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 6096 } 6097 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6098 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6099 } 6100 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 6101 newn = 0; 6102 for (v = 0; v < numValues; ++v) { 6103 IS tmp; 6104 const PetscInt *idx; 6105 6106 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6107 if (!tmp) continue; 6108 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6109 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6110 if (isFE[field]) { 6111 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 6112 } else { 6113 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 6114 } 6115 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6116 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6117 } 6118 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 6119 } 6120 } 6121 /* Handle discretization */ 6122 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 6123 for (f = 0; f < numFields; ++f) { 6124 PetscObject obj; 6125 6126 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 6127 if (isFE[f]) { 6128 PetscFE fe = (PetscFE) obj; 6129 const PetscInt *numFieldDof; 6130 PetscInt d; 6131 6132 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 6133 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 6134 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 6135 } else { 6136 PetscFV fv = (PetscFV) obj; 6137 6138 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 6139 numDof[f*(dim+1)+dim] = numComp[f]; 6140 } 6141 } 6142 for (f = 0; f < numFields; ++f) { 6143 PetscInt d; 6144 for (d = 1; d < dim; ++d) { 6145 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."); 6146 } 6147 } 6148 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 6149 for (f = 0; f < numFields; ++f) { 6150 PetscFE fe; 6151 const char *name; 6152 6153 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 6154 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 6155 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 6156 } 6157 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 6158 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6159 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 6160 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 6161 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 6162 ierr = PetscFree(isFE);CHKERRQ(ierr); 6163 PetscFunctionReturn(0); 6164 } 6165 6166 #undef __FUNCT__ 6167 #define __FUNCT__ "DMPlexGetRegularRefinement" 6168 /*@ 6169 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6170 6171 Input Parameter: 6172 . dm - The DMPlex object 6173 6174 Output Parameter: 6175 . regular - The flag 6176 6177 Level: intermediate 6178 6179 .seealso: DMPlexSetRegularRefinement() 6180 @*/ 6181 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 6182 { 6183 PetscFunctionBegin; 6184 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6185 PetscValidPointer(regular, 2); 6186 *regular = ((DM_Plex *) dm->data)->regularRefinement; 6187 PetscFunctionReturn(0); 6188 } 6189 6190 #undef __FUNCT__ 6191 #define __FUNCT__ "DMPlexSetRegularRefinement" 6192 /*@ 6193 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6194 6195 Input Parameters: 6196 + dm - The DMPlex object 6197 - regular - The flag 6198 6199 Level: intermediate 6200 6201 .seealso: DMPlexGetRegularRefinement() 6202 @*/ 6203 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 6204 { 6205 PetscFunctionBegin; 6206 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6207 ((DM_Plex *) dm->data)->regularRefinement = regular; 6208 PetscFunctionReturn(0); 6209 } 6210 6211 /* anchors */ 6212 #undef __FUNCT__ 6213 #define __FUNCT__ "DMPlexGetAnchors" 6214 /*@ 6215 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 6216 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 6217 6218 not collective 6219 6220 Input Parameters: 6221 . dm - The DMPlex object 6222 6223 Output Parameters: 6224 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 6225 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 6226 6227 6228 Level: intermediate 6229 6230 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 6231 @*/ 6232 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 6233 { 6234 DM_Plex *plex = (DM_Plex *)dm->data; 6235 PetscErrorCode ierr; 6236 6237 PetscFunctionBegin; 6238 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6239 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 6240 if (anchorSection) *anchorSection = plex->anchorSection; 6241 if (anchorIS) *anchorIS = plex->anchorIS; 6242 PetscFunctionReturn(0); 6243 } 6244 6245 #undef __FUNCT__ 6246 #define __FUNCT__ "DMPlexSetAnchors" 6247 /*@ 6248 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 6249 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 6250 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 6251 6252 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 6253 DMGetConstraints() and filling in the entries in the constraint matrix. 6254 6255 collective on dm 6256 6257 Input Parameters: 6258 + dm - The DMPlex object 6259 . 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). 6260 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 6261 6262 The reference counts of anchorSection and anchorIS are incremented. 6263 6264 Level: intermediate 6265 6266 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 6267 @*/ 6268 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 6269 { 6270 DM_Plex *plex = (DM_Plex *)dm->data; 6271 PetscMPIInt result; 6272 PetscErrorCode ierr; 6273 6274 PetscFunctionBegin; 6275 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6276 if (anchorSection) { 6277 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 6278 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 6279 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 6280 } 6281 if (anchorIS) { 6282 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 6283 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 6284 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 6285 } 6286 6287 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 6288 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 6289 plex->anchorSection = anchorSection; 6290 6291 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 6292 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 6293 plex->anchorIS = anchorIS; 6294 6295 #if defined(PETSC_USE_DEBUG) 6296 if (anchorIS && anchorSection) { 6297 PetscInt size, a, pStart, pEnd; 6298 const PetscInt *anchors; 6299 6300 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6301 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 6302 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 6303 for (a = 0; a < size; a++) { 6304 PetscInt p; 6305 6306 p = anchors[a]; 6307 if (p >= pStart && p < pEnd) { 6308 PetscInt dof; 6309 6310 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6311 if (dof) { 6312 PetscErrorCode ierr2; 6313 6314 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 6315 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %d cannot be constrained and an anchor",p); 6316 } 6317 } 6318 } 6319 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 6320 } 6321 #endif 6322 /* reset the generic constraints */ 6323 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 6324 PetscFunctionReturn(0); 6325 } 6326 6327 #undef __FUNCT__ 6328 #define __FUNCT__ "DMPlexCreateConstraintSection_Anchors" 6329 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 6330 { 6331 PetscSection anchorSection; 6332 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 6333 PetscErrorCode ierr; 6334 6335 PetscFunctionBegin; 6336 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6337 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6338 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 6339 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6340 if (numFields) { 6341 PetscInt f; 6342 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 6343 6344 for (f = 0; f < numFields; f++) { 6345 PetscInt numComp; 6346 6347 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 6348 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 6349 } 6350 } 6351 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6352 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 6353 pStart = PetscMax(pStart,sStart); 6354 pEnd = PetscMin(pEnd,sEnd); 6355 pEnd = PetscMax(pStart,pEnd); 6356 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 6357 for (p = pStart; p < pEnd; p++) { 6358 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6359 if (dof) { 6360 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 6361 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 6362 for (f = 0; f < numFields; f++) { 6363 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 6364 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 6365 } 6366 } 6367 } 6368 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 6369 PetscFunctionReturn(0); 6370 } 6371 6372 #undef __FUNCT__ 6373 #define __FUNCT__ "DMPlexCreateConstraintMatrix_Anchors" 6374 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 6375 { 6376 PetscSection aSec; 6377 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 6378 const PetscInt *anchors; 6379 PetscInt numFields, f; 6380 IS aIS; 6381 PetscErrorCode ierr; 6382 6383 PetscFunctionBegin; 6384 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6385 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 6386 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 6387 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 6388 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 6389 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 6390 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6391 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6392 /* cSec will be a subset of aSec and section */ 6393 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 6394 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 6395 i[0] = 0; 6396 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6397 for (p = pStart; p < pEnd; p++) { 6398 PetscInt rDof, rOff, r; 6399 6400 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6401 if (!rDof) continue; 6402 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6403 if (numFields) { 6404 for (f = 0; f < numFields; f++) { 6405 annz = 0; 6406 for (r = 0; r < rDof; r++) { 6407 a = anchors[rOff + r]; 6408 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6409 annz += aDof; 6410 } 6411 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6412 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 6413 for (q = 0; q < dof; q++) { 6414 i[off + q + 1] = i[off + q] + annz; 6415 } 6416 } 6417 } 6418 else { 6419 annz = 0; 6420 for (q = 0; q < dof; q++) { 6421 a = anchors[off + q]; 6422 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6423 annz += aDof; 6424 } 6425 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6426 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 6427 for (q = 0; q < dof; q++) { 6428 i[off + q + 1] = i[off + q] + annz; 6429 } 6430 } 6431 } 6432 nnz = i[m]; 6433 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 6434 offset = 0; 6435 for (p = pStart; p < pEnd; p++) { 6436 if (numFields) { 6437 for (f = 0; f < numFields; f++) { 6438 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6439 for (q = 0; q < dof; q++) { 6440 PetscInt rDof, rOff, r; 6441 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6442 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6443 for (r = 0; r < rDof; r++) { 6444 PetscInt s; 6445 6446 a = anchors[rOff + r]; 6447 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6448 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 6449 for (s = 0; s < aDof; s++) { 6450 j[offset++] = aOff + s; 6451 } 6452 } 6453 } 6454 } 6455 } 6456 else { 6457 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6458 for (q = 0; q < dof; q++) { 6459 PetscInt rDof, rOff, r; 6460 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6461 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6462 for (r = 0; r < rDof; r++) { 6463 PetscInt s; 6464 6465 a = anchors[rOff + r]; 6466 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6467 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 6468 for (s = 0; s < aDof; s++) { 6469 j[offset++] = aOff + s; 6470 } 6471 } 6472 } 6473 } 6474 } 6475 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 6476 ierr = PetscFree(i);CHKERRQ(ierr); 6477 ierr = PetscFree(j);CHKERRQ(ierr); 6478 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 6479 PetscFunctionReturn(0); 6480 } 6481 6482 #undef __FUNCT__ 6483 #define __FUNCT__ "DMCreateDefaultConstraints_Plex" 6484 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 6485 { 6486 DM_Plex *plex = (DM_Plex *)dm->data; 6487 PetscSection anchorSection, section, cSec; 6488 Mat cMat; 6489 PetscErrorCode ierr; 6490 6491 PetscFunctionBegin; 6492 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6493 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6494 if (anchorSection) { 6495 PetscDS ds; 6496 PetscInt nf; 6497 6498 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 6499 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 6500 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 6501 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 6502 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 6503 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 6504 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 6505 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 6506 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 6507 } 6508 PetscFunctionReturn(0); 6509 } 6510