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 = PetscFree(mesh->supports);CHKERRQ(ierr); 881 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 882 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 883 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 884 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 885 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 886 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 887 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 888 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 889 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 890 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 891 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 892 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 893 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 894 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 895 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 896 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 897 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 898 ierr = PetscFree(mesh);CHKERRQ(ierr); 899 PetscFunctionReturn(0); 900 } 901 902 #undef __FUNCT__ 903 #define __FUNCT__ "DMCreateMatrix_Plex" 904 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 905 { 906 PetscSection sectionGlobal; 907 PetscInt bs = -1, mbs; 908 PetscInt localSize; 909 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock; 910 PetscErrorCode ierr; 911 MatType mtype; 912 ISLocalToGlobalMapping ltog; 913 914 PetscFunctionBegin; 915 ierr = MatInitializePackage();CHKERRQ(ierr); 916 mtype = dm->mattype; 917 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 918 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 919 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 920 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 921 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 922 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 923 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 924 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 925 if (mbs > 1) bs = mbs; 926 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 927 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 928 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 929 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 930 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 931 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 932 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 933 if (!isShell) { 934 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 935 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 936 PetscInt pStart, pEnd, p, dof, cdof; 937 938 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 939 for (p = pStart; p < pEnd; ++p) { 940 PetscInt bdof; 941 942 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 943 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 944 dof = dof < 0 ? -(dof+1) : dof; 945 bdof = cdof && (dof-cdof) ? 1 : dof; 946 if (dof) { 947 if (bs < 0) {bs = bdof;} 948 else if (bs != bdof) {bs = 1; break;} 949 } 950 } 951 /* Must have same blocksize on all procs (some might have no points) */ 952 bsLocal = bs; 953 ierr = MPIU_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 954 bsLocal = bs < 0 ? bsMax : bs; 955 ierr = MPIU_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 956 if (bsMin != bsMax) {bs = 1;} 957 else {bs = bsMax;} 958 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 959 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 960 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 961 962 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work */ 963 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 964 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 965 } 966 PetscFunctionReturn(0); 967 } 968 969 #undef __FUNCT__ 970 #define __FUNCT__ "DMPlexGetChart" 971 /*@ 972 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 973 974 Not collective 975 976 Input Parameter: 977 . mesh - The DMPlex 978 979 Output Parameters: 980 + pStart - The first mesh point 981 - pEnd - The upper bound for mesh points 982 983 Level: beginner 984 985 .seealso: DMPlexCreate(), DMPlexSetChart() 986 @*/ 987 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 988 { 989 DM_Plex *mesh = (DM_Plex*) dm->data; 990 PetscErrorCode ierr; 991 992 PetscFunctionBegin; 993 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 994 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 995 PetscFunctionReturn(0); 996 } 997 998 #undef __FUNCT__ 999 #define __FUNCT__ "DMPlexSetChart" 1000 /*@ 1001 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1002 1003 Not collective 1004 1005 Input Parameters: 1006 + mesh - The DMPlex 1007 . pStart - The first mesh point 1008 - pEnd - The upper bound for mesh points 1009 1010 Output Parameters: 1011 1012 Level: beginner 1013 1014 .seealso: DMPlexCreate(), DMPlexGetChart() 1015 @*/ 1016 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1017 { 1018 DM_Plex *mesh = (DM_Plex*) dm->data; 1019 PetscErrorCode ierr; 1020 1021 PetscFunctionBegin; 1022 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1023 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1024 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1025 PetscFunctionReturn(0); 1026 } 1027 1028 #undef __FUNCT__ 1029 #define __FUNCT__ "DMPlexGetConeSize" 1030 /*@ 1031 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1032 1033 Not collective 1034 1035 Input Parameters: 1036 + mesh - The DMPlex 1037 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1038 1039 Output Parameter: 1040 . size - The cone size for point p 1041 1042 Level: beginner 1043 1044 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1045 @*/ 1046 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1047 { 1048 DM_Plex *mesh = (DM_Plex*) dm->data; 1049 PetscErrorCode ierr; 1050 1051 PetscFunctionBegin; 1052 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1053 PetscValidPointer(size, 3); 1054 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1055 PetscFunctionReturn(0); 1056 } 1057 1058 #undef __FUNCT__ 1059 #define __FUNCT__ "DMPlexSetConeSize" 1060 /*@ 1061 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1062 1063 Not collective 1064 1065 Input Parameters: 1066 + mesh - The DMPlex 1067 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1068 - size - The cone size for point p 1069 1070 Output Parameter: 1071 1072 Note: 1073 This should be called after DMPlexSetChart(). 1074 1075 Level: beginner 1076 1077 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1078 @*/ 1079 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1080 { 1081 DM_Plex *mesh = (DM_Plex*) dm->data; 1082 PetscErrorCode ierr; 1083 1084 PetscFunctionBegin; 1085 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1086 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1087 1088 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1089 PetscFunctionReturn(0); 1090 } 1091 1092 #undef __FUNCT__ 1093 #define __FUNCT__ "DMPlexAddConeSize" 1094 /*@ 1095 DMPlexAddConeSize - Add the given number of in-edges to this point in the Sieve DAG 1096 1097 Not collective 1098 1099 Input Parameters: 1100 + mesh - The DMPlex 1101 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1102 - size - The additional cone size for point p 1103 1104 Output Parameter: 1105 1106 Note: 1107 This should be called after DMPlexSetChart(). 1108 1109 Level: beginner 1110 1111 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 1112 @*/ 1113 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 1114 { 1115 DM_Plex *mesh = (DM_Plex*) dm->data; 1116 PetscInt csize; 1117 PetscErrorCode ierr; 1118 1119 PetscFunctionBegin; 1120 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1121 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1122 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 1123 1124 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 1125 PetscFunctionReturn(0); 1126 } 1127 1128 #undef __FUNCT__ 1129 #define __FUNCT__ "DMPlexGetCone" 1130 /*@C 1131 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1132 1133 Not collective 1134 1135 Input Parameters: 1136 + mesh - The DMPlex 1137 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1138 1139 Output Parameter: 1140 . cone - An array of points which are on the in-edges for point p 1141 1142 Level: beginner 1143 1144 Fortran Notes: 1145 Since it returns an array, this routine is only available in Fortran 90, and you must 1146 include petsc.h90 in your code. 1147 1148 You must also call DMPlexRestoreCone() after you finish using the returned array. 1149 1150 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1151 @*/ 1152 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1153 { 1154 DM_Plex *mesh = (DM_Plex*) dm->data; 1155 PetscInt off; 1156 PetscErrorCode ierr; 1157 1158 PetscFunctionBegin; 1159 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1160 PetscValidPointer(cone, 3); 1161 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1162 *cone = &mesh->cones[off]; 1163 PetscFunctionReturn(0); 1164 } 1165 1166 #undef __FUNCT__ 1167 #define __FUNCT__ "DMPlexSetCone" 1168 /*@ 1169 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1170 1171 Not collective 1172 1173 Input Parameters: 1174 + mesh - The DMPlex 1175 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1176 - cone - An array of points which are on the in-edges for point p 1177 1178 Output Parameter: 1179 1180 Note: 1181 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1182 1183 Level: beginner 1184 1185 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1186 @*/ 1187 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1188 { 1189 DM_Plex *mesh = (DM_Plex*) dm->data; 1190 PetscInt pStart, pEnd; 1191 PetscInt dof, off, c; 1192 PetscErrorCode ierr; 1193 1194 PetscFunctionBegin; 1195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1196 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1197 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1198 if (dof) PetscValidPointer(cone, 3); 1199 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1200 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); 1201 for (c = 0; c < dof; ++c) { 1202 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); 1203 mesh->cones[off+c] = cone[c]; 1204 } 1205 PetscFunctionReturn(0); 1206 } 1207 1208 #undef __FUNCT__ 1209 #define __FUNCT__ "DMPlexGetConeOrientation" 1210 /*@C 1211 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1212 1213 Not collective 1214 1215 Input Parameters: 1216 + mesh - The DMPlex 1217 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1218 1219 Output Parameter: 1220 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1221 integer giving the prescription for cone traversal. If it is negative, the cone is 1222 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1223 the index of the cone point on which to start. 1224 1225 Level: beginner 1226 1227 Fortran Notes: 1228 Since it returns an array, this routine is only available in Fortran 90, and you must 1229 include petsc.h90 in your code. 1230 1231 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 1232 1233 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1234 @*/ 1235 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1236 { 1237 DM_Plex *mesh = (DM_Plex*) dm->data; 1238 PetscInt off; 1239 PetscErrorCode ierr; 1240 1241 PetscFunctionBegin; 1242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1243 #if defined(PETSC_USE_DEBUG) 1244 { 1245 PetscInt dof; 1246 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1247 if (dof) PetscValidPointer(coneOrientation, 3); 1248 } 1249 #endif 1250 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1251 1252 *coneOrientation = &mesh->coneOrientations[off]; 1253 PetscFunctionReturn(0); 1254 } 1255 1256 #undef __FUNCT__ 1257 #define __FUNCT__ "DMPlexSetConeOrientation" 1258 /*@ 1259 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1260 1261 Not collective 1262 1263 Input Parameters: 1264 + mesh - The DMPlex 1265 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1266 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1267 integer giving the prescription for cone traversal. If it is negative, the cone is 1268 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1269 the index of the cone point on which to start. 1270 1271 Output Parameter: 1272 1273 Note: 1274 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1275 1276 Level: beginner 1277 1278 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1279 @*/ 1280 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1281 { 1282 DM_Plex *mesh = (DM_Plex*) dm->data; 1283 PetscInt pStart, pEnd; 1284 PetscInt dof, off, c; 1285 PetscErrorCode ierr; 1286 1287 PetscFunctionBegin; 1288 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1289 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1290 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1291 if (dof) PetscValidPointer(coneOrientation, 3); 1292 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1293 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); 1294 for (c = 0; c < dof; ++c) { 1295 PetscInt cdof, o = coneOrientation[c]; 1296 1297 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1298 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); 1299 mesh->coneOrientations[off+c] = o; 1300 } 1301 PetscFunctionReturn(0); 1302 } 1303 1304 #undef __FUNCT__ 1305 #define __FUNCT__ "DMPlexInsertCone" 1306 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1307 { 1308 DM_Plex *mesh = (DM_Plex*) dm->data; 1309 PetscInt pStart, pEnd; 1310 PetscInt dof, off; 1311 PetscErrorCode ierr; 1312 1313 PetscFunctionBegin; 1314 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1315 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1316 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); 1317 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); 1318 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1319 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1320 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); 1321 mesh->cones[off+conePos] = conePoint; 1322 PetscFunctionReturn(0); 1323 } 1324 1325 #undef __FUNCT__ 1326 #define __FUNCT__ "DMPlexInsertConeOrientation" 1327 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 1328 { 1329 DM_Plex *mesh = (DM_Plex*) dm->data; 1330 PetscInt pStart, pEnd; 1331 PetscInt dof, off; 1332 PetscErrorCode ierr; 1333 1334 PetscFunctionBegin; 1335 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1336 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1337 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); 1338 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1339 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1340 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); 1341 mesh->coneOrientations[off+conePos] = coneOrientation; 1342 PetscFunctionReturn(0); 1343 } 1344 1345 #undef __FUNCT__ 1346 #define __FUNCT__ "DMPlexGetSupportSize" 1347 /*@ 1348 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1349 1350 Not collective 1351 1352 Input Parameters: 1353 + mesh - The DMPlex 1354 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1355 1356 Output Parameter: 1357 . size - The support size for point p 1358 1359 Level: beginner 1360 1361 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1362 @*/ 1363 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1364 { 1365 DM_Plex *mesh = (DM_Plex*) dm->data; 1366 PetscErrorCode ierr; 1367 1368 PetscFunctionBegin; 1369 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1370 PetscValidPointer(size, 3); 1371 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1372 PetscFunctionReturn(0); 1373 } 1374 1375 #undef __FUNCT__ 1376 #define __FUNCT__ "DMPlexSetSupportSize" 1377 /*@ 1378 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1379 1380 Not collective 1381 1382 Input Parameters: 1383 + mesh - The DMPlex 1384 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1385 - size - The support size for point p 1386 1387 Output Parameter: 1388 1389 Note: 1390 This should be called after DMPlexSetChart(). 1391 1392 Level: beginner 1393 1394 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1395 @*/ 1396 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1397 { 1398 DM_Plex *mesh = (DM_Plex*) dm->data; 1399 PetscErrorCode ierr; 1400 1401 PetscFunctionBegin; 1402 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1403 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1404 1405 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1406 PetscFunctionReturn(0); 1407 } 1408 1409 #undef __FUNCT__ 1410 #define __FUNCT__ "DMPlexGetSupport" 1411 /*@C 1412 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1413 1414 Not collective 1415 1416 Input Parameters: 1417 + mesh - The DMPlex 1418 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1419 1420 Output Parameter: 1421 . support - An array of points which are on the out-edges for point p 1422 1423 Level: beginner 1424 1425 Fortran Notes: 1426 Since it returns an array, this routine is only available in Fortran 90, and you must 1427 include petsc.h90 in your code. 1428 1429 You must also call DMPlexRestoreSupport() after you finish using the returned array. 1430 1431 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1432 @*/ 1433 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1434 { 1435 DM_Plex *mesh = (DM_Plex*) dm->data; 1436 PetscInt off; 1437 PetscErrorCode ierr; 1438 1439 PetscFunctionBegin; 1440 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1441 PetscValidPointer(support, 3); 1442 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1443 *support = &mesh->supports[off]; 1444 PetscFunctionReturn(0); 1445 } 1446 1447 #undef __FUNCT__ 1448 #define __FUNCT__ "DMPlexSetSupport" 1449 /*@ 1450 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1451 1452 Not collective 1453 1454 Input Parameters: 1455 + mesh - The DMPlex 1456 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1457 - support - An array of points which are on the in-edges for point p 1458 1459 Output Parameter: 1460 1461 Note: 1462 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1463 1464 Level: beginner 1465 1466 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1467 @*/ 1468 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1469 { 1470 DM_Plex *mesh = (DM_Plex*) dm->data; 1471 PetscInt pStart, pEnd; 1472 PetscInt dof, off, c; 1473 PetscErrorCode ierr; 1474 1475 PetscFunctionBegin; 1476 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1477 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1478 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1479 if (dof) PetscValidPointer(support, 3); 1480 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1481 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); 1482 for (c = 0; c < dof; ++c) { 1483 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); 1484 mesh->supports[off+c] = support[c]; 1485 } 1486 PetscFunctionReturn(0); 1487 } 1488 1489 #undef __FUNCT__ 1490 #define __FUNCT__ "DMPlexInsertSupport" 1491 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1492 { 1493 DM_Plex *mesh = (DM_Plex*) dm->data; 1494 PetscInt pStart, pEnd; 1495 PetscInt dof, off; 1496 PetscErrorCode ierr; 1497 1498 PetscFunctionBegin; 1499 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1500 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1501 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1502 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1503 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); 1504 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); 1505 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); 1506 mesh->supports[off+supportPos] = supportPoint; 1507 PetscFunctionReturn(0); 1508 } 1509 1510 #undef __FUNCT__ 1511 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1512 /*@C 1513 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1514 1515 Not collective 1516 1517 Input Parameters: 1518 + mesh - The DMPlex 1519 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1520 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1521 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1522 1523 Output Parameters: 1524 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1525 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1526 1527 Note: 1528 If using internal storage (points is NULL on input), each call overwrites the last output. 1529 1530 Fortran Notes: 1531 Since it returns an array, this routine is only available in Fortran 90, and you must 1532 include petsc.h90 in your code. 1533 1534 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1535 1536 Level: beginner 1537 1538 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1539 @*/ 1540 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1541 { 1542 DM_Plex *mesh = (DM_Plex*) dm->data; 1543 PetscInt *closure, *fifo; 1544 const PetscInt *tmp = NULL, *tmpO = NULL; 1545 PetscInt tmpSize, t; 1546 PetscInt depth = 0, maxSize; 1547 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1548 PetscErrorCode ierr; 1549 1550 PetscFunctionBegin; 1551 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1552 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1553 /* This is only 1-level */ 1554 if (useCone) { 1555 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1556 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1557 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1558 } else { 1559 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1560 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1561 } 1562 if (depth == 1) { 1563 if (*points) { 1564 closure = *points; 1565 } else { 1566 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 1567 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1568 } 1569 closure[0] = p; closure[1] = 0; 1570 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 1571 closure[closureSize] = tmp[t]; 1572 closure[closureSize+1] = tmpO ? tmpO[t] : 0; 1573 } 1574 if (numPoints) *numPoints = closureSize/2; 1575 if (points) *points = closure; 1576 PetscFunctionReturn(0); 1577 } 1578 { 1579 PetscInt c, coneSeries, s,supportSeries; 1580 1581 c = mesh->maxConeSize; 1582 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 1583 s = mesh->maxSupportSize; 1584 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 1585 maxSize = 2*PetscMax(coneSeries,supportSeries); 1586 } 1587 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1588 if (*points) { 1589 closure = *points; 1590 } else { 1591 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1592 } 1593 closure[0] = p; closure[1] = 0; 1594 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1595 const PetscInt cp = tmp[t]; 1596 const PetscInt co = tmpO ? tmpO[t] : 0; 1597 1598 closure[closureSize] = cp; 1599 closure[closureSize+1] = co; 1600 fifo[fifoSize] = cp; 1601 fifo[fifoSize+1] = co; 1602 } 1603 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 1604 while (fifoSize - fifoStart) { 1605 const PetscInt q = fifo[fifoStart]; 1606 const PetscInt o = fifo[fifoStart+1]; 1607 const PetscInt rev = o >= 0 ? 0 : 1; 1608 const PetscInt off = rev ? -(o+1) : o; 1609 1610 if (useCone) { 1611 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1612 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1613 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1614 } else { 1615 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1616 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1617 tmpO = NULL; 1618 } 1619 for (t = 0; t < tmpSize; ++t) { 1620 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1621 const PetscInt cp = tmp[i]; 1622 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 1623 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 1624 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 1625 PetscInt co = tmpO ? tmpO[i] : 0; 1626 PetscInt c; 1627 1628 if (rev) { 1629 PetscInt childSize, coff; 1630 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1631 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1632 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1633 } 1634 /* Check for duplicate */ 1635 for (c = 0; c < closureSize; c += 2) { 1636 if (closure[c] == cp) break; 1637 } 1638 if (c == closureSize) { 1639 closure[closureSize] = cp; 1640 closure[closureSize+1] = co; 1641 fifo[fifoSize] = cp; 1642 fifo[fifoSize+1] = co; 1643 closureSize += 2; 1644 fifoSize += 2; 1645 } 1646 } 1647 fifoStart += 2; 1648 } 1649 if (numPoints) *numPoints = closureSize/2; 1650 if (points) *points = closure; 1651 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1652 PetscFunctionReturn(0); 1653 } 1654 1655 #undef __FUNCT__ 1656 #define __FUNCT__ "DMPlexGetTransitiveClosure_Internal" 1657 /*@C 1658 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 1659 1660 Not collective 1661 1662 Input Parameters: 1663 + mesh - The DMPlex 1664 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1665 . orientation - The orientation of the point 1666 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1667 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1668 1669 Output Parameters: 1670 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1671 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1672 1673 Note: 1674 If using internal storage (points is NULL on input), each call overwrites the last output. 1675 1676 Fortran Notes: 1677 Since it returns an array, this routine is only available in Fortran 90, and you must 1678 include petsc.h90 in your code. 1679 1680 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1681 1682 Level: beginner 1683 1684 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1685 @*/ 1686 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1687 { 1688 DM_Plex *mesh = (DM_Plex*) dm->data; 1689 PetscInt *closure, *fifo; 1690 const PetscInt *tmp = NULL, *tmpO = NULL; 1691 PetscInt tmpSize, t; 1692 PetscInt depth = 0, maxSize; 1693 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1694 PetscErrorCode ierr; 1695 1696 PetscFunctionBegin; 1697 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1698 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1699 /* This is only 1-level */ 1700 if (useCone) { 1701 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1702 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1703 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1704 } else { 1705 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1706 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1707 } 1708 if (depth == 1) { 1709 if (*points) { 1710 closure = *points; 1711 } else { 1712 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 1713 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1714 } 1715 closure[0] = p; closure[1] = ornt; 1716 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 1717 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 1718 closure[closureSize] = tmp[i]; 1719 closure[closureSize+1] = tmpO ? tmpO[i] : 0; 1720 } 1721 if (numPoints) *numPoints = closureSize/2; 1722 if (points) *points = closure; 1723 PetscFunctionReturn(0); 1724 } 1725 { 1726 PetscInt c, coneSeries, s,supportSeries; 1727 1728 c = mesh->maxConeSize; 1729 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 1730 s = mesh->maxSupportSize; 1731 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 1732 maxSize = 2*PetscMax(coneSeries,supportSeries); 1733 } 1734 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1735 if (*points) { 1736 closure = *points; 1737 } else { 1738 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1739 } 1740 closure[0] = p; closure[1] = ornt; 1741 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1742 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 1743 const PetscInt cp = tmp[i]; 1744 PetscInt co = tmpO ? tmpO[i] : 0; 1745 1746 if (ornt < 0) { 1747 PetscInt childSize, coff; 1748 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1749 coff = co < 0 ? -(tmpO[i]+1) : tmpO[i]; 1750 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1751 } 1752 closure[closureSize] = cp; 1753 closure[closureSize+1] = co; 1754 fifo[fifoSize] = cp; 1755 fifo[fifoSize+1] = co; 1756 } 1757 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 1758 while (fifoSize - fifoStart) { 1759 const PetscInt q = fifo[fifoStart]; 1760 const PetscInt o = fifo[fifoStart+1]; 1761 const PetscInt rev = o >= 0 ? 0 : 1; 1762 const PetscInt off = rev ? -(o+1) : o; 1763 1764 if (useCone) { 1765 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1766 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1767 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1768 } else { 1769 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1770 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1771 tmpO = NULL; 1772 } 1773 for (t = 0; t < tmpSize; ++t) { 1774 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1775 const PetscInt cp = tmp[i]; 1776 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 1777 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 1778 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 1779 PetscInt co = tmpO ? tmpO[i] : 0; 1780 PetscInt c; 1781 1782 if (rev) { 1783 PetscInt childSize, coff; 1784 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1785 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1786 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1787 } 1788 /* Check for duplicate */ 1789 for (c = 0; c < closureSize; c += 2) { 1790 if (closure[c] == cp) break; 1791 } 1792 if (c == closureSize) { 1793 closure[closureSize] = cp; 1794 closure[closureSize+1] = co; 1795 fifo[fifoSize] = cp; 1796 fifo[fifoSize+1] = co; 1797 closureSize += 2; 1798 fifoSize += 2; 1799 } 1800 } 1801 fifoStart += 2; 1802 } 1803 if (numPoints) *numPoints = closureSize/2; 1804 if (points) *points = closure; 1805 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1806 PetscFunctionReturn(0); 1807 } 1808 1809 #undef __FUNCT__ 1810 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1811 /*@C 1812 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1813 1814 Not collective 1815 1816 Input Parameters: 1817 + mesh - The DMPlex 1818 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1819 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1820 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 1821 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 1822 1823 Note: 1824 If not using internal storage (points is not NULL on input), this call is unnecessary 1825 1826 Fortran Notes: 1827 Since it returns an array, this routine is only available in Fortran 90, and you must 1828 include petsc.h90 in your code. 1829 1830 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1831 1832 Level: beginner 1833 1834 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1835 @*/ 1836 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1837 { 1838 PetscErrorCode ierr; 1839 1840 PetscFunctionBegin; 1841 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1842 if (numPoints) PetscValidIntPointer(numPoints,4); 1843 if (points) PetscValidPointer(points,5); 1844 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1845 if (numPoints) *numPoints = 0; 1846 PetscFunctionReturn(0); 1847 } 1848 1849 #undef __FUNCT__ 1850 #define __FUNCT__ "DMPlexGetMaxSizes" 1851 /*@ 1852 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1853 1854 Not collective 1855 1856 Input Parameter: 1857 . mesh - The DMPlex 1858 1859 Output Parameters: 1860 + maxConeSize - The maximum number of in-edges 1861 - maxSupportSize - The maximum number of out-edges 1862 1863 Level: beginner 1864 1865 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1866 @*/ 1867 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1868 { 1869 DM_Plex *mesh = (DM_Plex*) dm->data; 1870 1871 PetscFunctionBegin; 1872 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1873 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1874 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1875 PetscFunctionReturn(0); 1876 } 1877 1878 #undef __FUNCT__ 1879 #define __FUNCT__ "DMSetUp_Plex" 1880 PetscErrorCode DMSetUp_Plex(DM dm) 1881 { 1882 DM_Plex *mesh = (DM_Plex*) dm->data; 1883 PetscInt size; 1884 PetscErrorCode ierr; 1885 1886 PetscFunctionBegin; 1887 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1888 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1889 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1890 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 1891 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 1892 if (mesh->maxSupportSize) { 1893 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1894 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1895 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 1896 } 1897 PetscFunctionReturn(0); 1898 } 1899 1900 #undef __FUNCT__ 1901 #define __FUNCT__ "DMCreateSubDM_Plex" 1902 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1903 { 1904 PetscErrorCode ierr; 1905 1906 PetscFunctionBegin; 1907 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 1908 ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1909 PetscFunctionReturn(0); 1910 } 1911 1912 #undef __FUNCT__ 1913 #define __FUNCT__ "DMPlexSymmetrize" 1914 /*@ 1915 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1916 1917 Not collective 1918 1919 Input Parameter: 1920 . mesh - The DMPlex 1921 1922 Output Parameter: 1923 1924 Note: 1925 This should be called after all calls to DMPlexSetCone() 1926 1927 Level: beginner 1928 1929 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1930 @*/ 1931 PetscErrorCode DMPlexSymmetrize(DM dm) 1932 { 1933 DM_Plex *mesh = (DM_Plex*) dm->data; 1934 PetscInt *offsets; 1935 PetscInt supportSize; 1936 PetscInt pStart, pEnd, p; 1937 PetscErrorCode ierr; 1938 1939 PetscFunctionBegin; 1940 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1941 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1942 /* Calculate support sizes */ 1943 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1944 for (p = pStart; p < pEnd; ++p) { 1945 PetscInt dof, off, c; 1946 1947 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1948 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1949 for (c = off; c < off+dof; ++c) { 1950 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1951 } 1952 } 1953 for (p = pStart; p < pEnd; ++p) { 1954 PetscInt dof; 1955 1956 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1957 1958 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1959 } 1960 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1961 /* Calculate supports */ 1962 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1963 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 1964 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 1965 for (p = pStart; p < pEnd; ++p) { 1966 PetscInt dof, off, c; 1967 1968 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1969 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1970 for (c = off; c < off+dof; ++c) { 1971 const PetscInt q = mesh->cones[c]; 1972 PetscInt offS; 1973 1974 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1975 1976 mesh->supports[offS+offsets[q]] = p; 1977 ++offsets[q]; 1978 } 1979 } 1980 ierr = PetscFree(offsets);CHKERRQ(ierr); 1981 PetscFunctionReturn(0); 1982 } 1983 1984 #undef __FUNCT__ 1985 #define __FUNCT__ "DMPlexStratify" 1986 /*@ 1987 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 1988 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 1989 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 1990 the DAG. 1991 1992 Collective on dm 1993 1994 Input Parameter: 1995 . mesh - The DMPlex 1996 1997 Output Parameter: 1998 1999 Notes: 2000 Concretely, DMPlexStratify() creates a new label named "depth" containing the dimension of each element: 0 for vertices, 2001 1 for edges, and so on. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 2002 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 2003 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 2004 2005 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 2006 2007 Level: beginner 2008 2009 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2010 @*/ 2011 PetscErrorCode DMPlexStratify(DM dm) 2012 { 2013 DM_Plex *mesh = (DM_Plex*) dm->data; 2014 DMLabel label; 2015 PetscInt pStart, pEnd, p; 2016 PetscInt numRoots = 0, numLeaves = 0; 2017 PetscErrorCode ierr; 2018 2019 PetscFunctionBegin; 2020 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2021 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2022 /* Calculate depth */ 2023 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2024 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 2025 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2026 /* Initialize roots and count leaves */ 2027 for (p = pStart; p < pEnd; ++p) { 2028 PetscInt coneSize, supportSize; 2029 2030 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2031 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2032 if (!coneSize && supportSize) { 2033 ++numRoots; 2034 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 2035 } else if (!supportSize && coneSize) { 2036 ++numLeaves; 2037 } else if (!supportSize && !coneSize) { 2038 /* Isolated points */ 2039 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 2040 } 2041 } 2042 if (numRoots + numLeaves == (pEnd - pStart)) { 2043 for (p = pStart; p < pEnd; ++p) { 2044 PetscInt coneSize, supportSize; 2045 2046 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2047 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2048 if (!supportSize && coneSize) { 2049 ierr = DMLabelSetValue(label, p, 1);CHKERRQ(ierr); 2050 } 2051 } 2052 } else { 2053 IS pointIS; 2054 PetscInt numPoints = 0, level = 0; 2055 2056 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 2057 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 2058 while (numPoints) { 2059 const PetscInt *points; 2060 const PetscInt newLevel = level+1; 2061 2062 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 2063 for (p = 0; p < numPoints; ++p) { 2064 const PetscInt point = points[p]; 2065 const PetscInt *support; 2066 PetscInt supportSize, s; 2067 2068 ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr); 2069 ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 2070 for (s = 0; s < supportSize; ++s) { 2071 ierr = DMLabelSetValue(label, support[s], newLevel);CHKERRQ(ierr); 2072 } 2073 } 2074 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 2075 ++level; 2076 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2077 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 2078 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 2079 else {numPoints = 0;} 2080 } 2081 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2082 } 2083 { /* just in case there is an empty process */ 2084 PetscInt numValues, maxValues = 0, v; 2085 2086 ierr = DMLabelGetNumValues(label,&numValues);CHKERRQ(ierr); 2087 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 2088 for (v = numValues; v < maxValues; v++) { 2089 DMLabelAddStratum(label,v);CHKERRQ(ierr); 2090 } 2091 } 2092 2093 ierr = DMLabelGetState(label, &mesh->depthState);CHKERRQ(ierr); 2094 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2095 PetscFunctionReturn(0); 2096 } 2097 2098 #undef __FUNCT__ 2099 #define __FUNCT__ "DMPlexGetJoin" 2100 /*@C 2101 DMPlexGetJoin - Get an array for the join of the set of points 2102 2103 Not Collective 2104 2105 Input Parameters: 2106 + dm - The DMPlex object 2107 . numPoints - The number of input points for the join 2108 - points - The input points 2109 2110 Output Parameters: 2111 + numCoveredPoints - The number of points in the join 2112 - coveredPoints - The points in the join 2113 2114 Level: intermediate 2115 2116 Note: Currently, this is restricted to a single level join 2117 2118 Fortran Notes: 2119 Since it returns an array, this routine is only available in Fortran 90, and you must 2120 include petsc.h90 in your code. 2121 2122 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2123 2124 .keywords: mesh 2125 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2126 @*/ 2127 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2128 { 2129 DM_Plex *mesh = (DM_Plex*) dm->data; 2130 PetscInt *join[2]; 2131 PetscInt joinSize, i = 0; 2132 PetscInt dof, off, p, c, m; 2133 PetscErrorCode ierr; 2134 2135 PetscFunctionBegin; 2136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2137 PetscValidPointer(points, 2); 2138 PetscValidPointer(numCoveredPoints, 3); 2139 PetscValidPointer(coveredPoints, 4); 2140 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2141 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2142 /* Copy in support of first point */ 2143 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2144 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2145 for (joinSize = 0; joinSize < dof; ++joinSize) { 2146 join[i][joinSize] = mesh->supports[off+joinSize]; 2147 } 2148 /* Check each successive support */ 2149 for (p = 1; p < numPoints; ++p) { 2150 PetscInt newJoinSize = 0; 2151 2152 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2153 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2154 for (c = 0; c < dof; ++c) { 2155 const PetscInt point = mesh->supports[off+c]; 2156 2157 for (m = 0; m < joinSize; ++m) { 2158 if (point == join[i][m]) { 2159 join[1-i][newJoinSize++] = point; 2160 break; 2161 } 2162 } 2163 } 2164 joinSize = newJoinSize; 2165 i = 1-i; 2166 } 2167 *numCoveredPoints = joinSize; 2168 *coveredPoints = join[i]; 2169 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2170 PetscFunctionReturn(0); 2171 } 2172 2173 #undef __FUNCT__ 2174 #define __FUNCT__ "DMPlexRestoreJoin" 2175 /*@C 2176 DMPlexRestoreJoin - Restore an array for the join of the set of points 2177 2178 Not Collective 2179 2180 Input Parameters: 2181 + dm - The DMPlex object 2182 . numPoints - The number of input points for the join 2183 - points - The input points 2184 2185 Output Parameters: 2186 + numCoveredPoints - The number of points in the join 2187 - coveredPoints - The points in the join 2188 2189 Fortran Notes: 2190 Since it returns an array, this routine is only available in Fortran 90, and you must 2191 include petsc.h90 in your code. 2192 2193 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2194 2195 Level: intermediate 2196 2197 .keywords: mesh 2198 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2199 @*/ 2200 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2201 { 2202 PetscErrorCode ierr; 2203 2204 PetscFunctionBegin; 2205 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2206 if (points) PetscValidIntPointer(points,3); 2207 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2208 PetscValidPointer(coveredPoints, 5); 2209 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2210 if (numCoveredPoints) *numCoveredPoints = 0; 2211 PetscFunctionReturn(0); 2212 } 2213 2214 #undef __FUNCT__ 2215 #define __FUNCT__ "DMPlexGetFullJoin" 2216 /*@C 2217 DMPlexGetFullJoin - Get an array for the join of the set of points 2218 2219 Not Collective 2220 2221 Input Parameters: 2222 + dm - The DMPlex object 2223 . numPoints - The number of input points for the join 2224 - points - The input points 2225 2226 Output Parameters: 2227 + numCoveredPoints - The number of points in the join 2228 - coveredPoints - The points in the join 2229 2230 Fortran Notes: 2231 Since it returns an array, this routine is only available in Fortran 90, and you must 2232 include petsc.h90 in your code. 2233 2234 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2235 2236 Level: intermediate 2237 2238 .keywords: mesh 2239 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2240 @*/ 2241 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2242 { 2243 DM_Plex *mesh = (DM_Plex*) dm->data; 2244 PetscInt *offsets, **closures; 2245 PetscInt *join[2]; 2246 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2247 PetscInt p, d, c, m, ms; 2248 PetscErrorCode ierr; 2249 2250 PetscFunctionBegin; 2251 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2252 PetscValidPointer(points, 2); 2253 PetscValidPointer(numCoveredPoints, 3); 2254 PetscValidPointer(coveredPoints, 4); 2255 2256 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2257 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 2258 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2259 ms = mesh->maxSupportSize; 2260 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 2261 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2262 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2263 2264 for (p = 0; p < numPoints; ++p) { 2265 PetscInt closureSize; 2266 2267 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2268 2269 offsets[p*(depth+2)+0] = 0; 2270 for (d = 0; d < depth+1; ++d) { 2271 PetscInt pStart, pEnd, i; 2272 2273 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2274 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2275 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2276 offsets[p*(depth+2)+d+1] = i; 2277 break; 2278 } 2279 } 2280 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2281 } 2282 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); 2283 } 2284 for (d = 0; d < depth+1; ++d) { 2285 PetscInt dof; 2286 2287 /* Copy in support of first point */ 2288 dof = offsets[d+1] - offsets[d]; 2289 for (joinSize = 0; joinSize < dof; ++joinSize) { 2290 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2291 } 2292 /* Check each successive cone */ 2293 for (p = 1; p < numPoints && joinSize; ++p) { 2294 PetscInt newJoinSize = 0; 2295 2296 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2297 for (c = 0; c < dof; ++c) { 2298 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2299 2300 for (m = 0; m < joinSize; ++m) { 2301 if (point == join[i][m]) { 2302 join[1-i][newJoinSize++] = point; 2303 break; 2304 } 2305 } 2306 } 2307 joinSize = newJoinSize; 2308 i = 1-i; 2309 } 2310 if (joinSize) break; 2311 } 2312 *numCoveredPoints = joinSize; 2313 *coveredPoints = join[i]; 2314 for (p = 0; p < numPoints; ++p) { 2315 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2316 } 2317 ierr = PetscFree(closures);CHKERRQ(ierr); 2318 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2319 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2320 PetscFunctionReturn(0); 2321 } 2322 2323 #undef __FUNCT__ 2324 #define __FUNCT__ "DMPlexGetMeet" 2325 /*@C 2326 DMPlexGetMeet - Get an array for the meet of the set of points 2327 2328 Not Collective 2329 2330 Input Parameters: 2331 + dm - The DMPlex object 2332 . numPoints - The number of input points for the meet 2333 - points - The input points 2334 2335 Output Parameters: 2336 + numCoveredPoints - The number of points in the meet 2337 - coveredPoints - The points in the meet 2338 2339 Level: intermediate 2340 2341 Note: Currently, this is restricted to a single level meet 2342 2343 Fortran Notes: 2344 Since it returns an array, this routine is only available in Fortran 90, and you must 2345 include petsc.h90 in your code. 2346 2347 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2348 2349 .keywords: mesh 2350 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2351 @*/ 2352 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2353 { 2354 DM_Plex *mesh = (DM_Plex*) dm->data; 2355 PetscInt *meet[2]; 2356 PetscInt meetSize, i = 0; 2357 PetscInt dof, off, p, c, m; 2358 PetscErrorCode ierr; 2359 2360 PetscFunctionBegin; 2361 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2362 PetscValidPointer(points, 2); 2363 PetscValidPointer(numCoveringPoints, 3); 2364 PetscValidPointer(coveringPoints, 4); 2365 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2366 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2367 /* Copy in cone of first point */ 2368 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2369 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2370 for (meetSize = 0; meetSize < dof; ++meetSize) { 2371 meet[i][meetSize] = mesh->cones[off+meetSize]; 2372 } 2373 /* Check each successive cone */ 2374 for (p = 1; p < numPoints; ++p) { 2375 PetscInt newMeetSize = 0; 2376 2377 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2378 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2379 for (c = 0; c < dof; ++c) { 2380 const PetscInt point = mesh->cones[off+c]; 2381 2382 for (m = 0; m < meetSize; ++m) { 2383 if (point == meet[i][m]) { 2384 meet[1-i][newMeetSize++] = point; 2385 break; 2386 } 2387 } 2388 } 2389 meetSize = newMeetSize; 2390 i = 1-i; 2391 } 2392 *numCoveringPoints = meetSize; 2393 *coveringPoints = meet[i]; 2394 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2395 PetscFunctionReturn(0); 2396 } 2397 2398 #undef __FUNCT__ 2399 #define __FUNCT__ "DMPlexRestoreMeet" 2400 /*@C 2401 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2402 2403 Not Collective 2404 2405 Input Parameters: 2406 + dm - The DMPlex object 2407 . numPoints - The number of input points for the meet 2408 - points - The input points 2409 2410 Output Parameters: 2411 + numCoveredPoints - The number of points in the meet 2412 - coveredPoints - The points in the meet 2413 2414 Level: intermediate 2415 2416 Fortran Notes: 2417 Since it returns an array, this routine is only available in Fortran 90, and you must 2418 include petsc.h90 in your code. 2419 2420 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2421 2422 .keywords: mesh 2423 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2424 @*/ 2425 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2426 { 2427 PetscErrorCode ierr; 2428 2429 PetscFunctionBegin; 2430 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2431 if (points) PetscValidIntPointer(points,3); 2432 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2433 PetscValidPointer(coveredPoints,5); 2434 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2435 if (numCoveredPoints) *numCoveredPoints = 0; 2436 PetscFunctionReturn(0); 2437 } 2438 2439 #undef __FUNCT__ 2440 #define __FUNCT__ "DMPlexGetFullMeet" 2441 /*@C 2442 DMPlexGetFullMeet - Get an array for the meet of the set of points 2443 2444 Not Collective 2445 2446 Input Parameters: 2447 + dm - The DMPlex object 2448 . numPoints - The number of input points for the meet 2449 - points - The input points 2450 2451 Output Parameters: 2452 + numCoveredPoints - The number of points in the meet 2453 - coveredPoints - The points in the meet 2454 2455 Level: intermediate 2456 2457 Fortran Notes: 2458 Since it returns an array, this routine is only available in Fortran 90, and you must 2459 include petsc.h90 in your code. 2460 2461 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2462 2463 .keywords: mesh 2464 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2465 @*/ 2466 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2467 { 2468 DM_Plex *mesh = (DM_Plex*) dm->data; 2469 PetscInt *offsets, **closures; 2470 PetscInt *meet[2]; 2471 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2472 PetscInt p, h, c, m, mc; 2473 PetscErrorCode ierr; 2474 2475 PetscFunctionBegin; 2476 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2477 PetscValidPointer(points, 2); 2478 PetscValidPointer(numCoveredPoints, 3); 2479 PetscValidPointer(coveredPoints, 4); 2480 2481 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2482 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 2483 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2484 mc = mesh->maxConeSize; 2485 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 2486 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2487 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2488 2489 for (p = 0; p < numPoints; ++p) { 2490 PetscInt closureSize; 2491 2492 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2493 2494 offsets[p*(height+2)+0] = 0; 2495 for (h = 0; h < height+1; ++h) { 2496 PetscInt pStart, pEnd, i; 2497 2498 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2499 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2500 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2501 offsets[p*(height+2)+h+1] = i; 2502 break; 2503 } 2504 } 2505 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2506 } 2507 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); 2508 } 2509 for (h = 0; h < height+1; ++h) { 2510 PetscInt dof; 2511 2512 /* Copy in cone of first point */ 2513 dof = offsets[h+1] - offsets[h]; 2514 for (meetSize = 0; meetSize < dof; ++meetSize) { 2515 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2516 } 2517 /* Check each successive cone */ 2518 for (p = 1; p < numPoints && meetSize; ++p) { 2519 PetscInt newMeetSize = 0; 2520 2521 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2522 for (c = 0; c < dof; ++c) { 2523 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2524 2525 for (m = 0; m < meetSize; ++m) { 2526 if (point == meet[i][m]) { 2527 meet[1-i][newMeetSize++] = point; 2528 break; 2529 } 2530 } 2531 } 2532 meetSize = newMeetSize; 2533 i = 1-i; 2534 } 2535 if (meetSize) break; 2536 } 2537 *numCoveredPoints = meetSize; 2538 *coveredPoints = meet[i]; 2539 for (p = 0; p < numPoints; ++p) { 2540 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2541 } 2542 ierr = PetscFree(closures);CHKERRQ(ierr); 2543 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2544 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2545 PetscFunctionReturn(0); 2546 } 2547 2548 #undef __FUNCT__ 2549 #define __FUNCT__ "DMPlexEqual" 2550 /*@C 2551 DMPlexEqual - Determine if two DMs have the same topology 2552 2553 Not Collective 2554 2555 Input Parameters: 2556 + dmA - A DMPlex object 2557 - dmB - A DMPlex object 2558 2559 Output Parameters: 2560 . equal - PETSC_TRUE if the topologies are identical 2561 2562 Level: intermediate 2563 2564 Notes: 2565 We are not solving graph isomorphism, so we do not permutation. 2566 2567 .keywords: mesh 2568 .seealso: DMPlexGetCone() 2569 @*/ 2570 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 2571 { 2572 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 2573 PetscErrorCode ierr; 2574 2575 PetscFunctionBegin; 2576 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 2577 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 2578 PetscValidPointer(equal, 3); 2579 2580 *equal = PETSC_FALSE; 2581 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 2582 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 2583 if (depth != depthB) PetscFunctionReturn(0); 2584 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 2585 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 2586 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 2587 for (p = pStart; p < pEnd; ++p) { 2588 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 2589 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 2590 2591 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 2592 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 2593 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 2594 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 2595 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 2596 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 2597 if (coneSize != coneSizeB) PetscFunctionReturn(0); 2598 for (c = 0; c < coneSize; ++c) { 2599 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 2600 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 2601 } 2602 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 2603 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 2604 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 2605 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 2606 if (supportSize != supportSizeB) PetscFunctionReturn(0); 2607 for (s = 0; s < supportSize; ++s) { 2608 if (support[s] != supportB[s]) PetscFunctionReturn(0); 2609 } 2610 } 2611 *equal = PETSC_TRUE; 2612 PetscFunctionReturn(0); 2613 } 2614 2615 #undef __FUNCT__ 2616 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2617 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2618 { 2619 MPI_Comm comm; 2620 PetscErrorCode ierr; 2621 2622 PetscFunctionBegin; 2623 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2624 PetscValidPointer(numFaceVertices,3); 2625 switch (cellDim) { 2626 case 0: 2627 *numFaceVertices = 0; 2628 break; 2629 case 1: 2630 *numFaceVertices = 1; 2631 break; 2632 case 2: 2633 switch (numCorners) { 2634 case 3: /* triangle */ 2635 *numFaceVertices = 2; /* Edge has 2 vertices */ 2636 break; 2637 case 4: /* quadrilateral */ 2638 *numFaceVertices = 2; /* Edge has 2 vertices */ 2639 break; 2640 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2641 *numFaceVertices = 3; /* Edge has 3 vertices */ 2642 break; 2643 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2644 *numFaceVertices = 3; /* Edge has 3 vertices */ 2645 break; 2646 default: 2647 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 2648 } 2649 break; 2650 case 3: 2651 switch (numCorners) { 2652 case 4: /* tetradehdron */ 2653 *numFaceVertices = 3; /* Face has 3 vertices */ 2654 break; 2655 case 6: /* tet cohesive cells */ 2656 *numFaceVertices = 4; /* Face has 4 vertices */ 2657 break; 2658 case 8: /* hexahedron */ 2659 *numFaceVertices = 4; /* Face has 4 vertices */ 2660 break; 2661 case 9: /* tet cohesive Lagrange cells */ 2662 *numFaceVertices = 6; /* Face has 6 vertices */ 2663 break; 2664 case 10: /* quadratic tetrahedron */ 2665 *numFaceVertices = 6; /* Face has 6 vertices */ 2666 break; 2667 case 12: /* hex cohesive Lagrange cells */ 2668 *numFaceVertices = 6; /* Face has 6 vertices */ 2669 break; 2670 case 18: /* quadratic tet cohesive Lagrange cells */ 2671 *numFaceVertices = 6; /* Face has 6 vertices */ 2672 break; 2673 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2674 *numFaceVertices = 9; /* Face has 9 vertices */ 2675 break; 2676 default: 2677 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 2678 } 2679 break; 2680 default: 2681 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 2682 } 2683 PetscFunctionReturn(0); 2684 } 2685 2686 #undef __FUNCT__ 2687 #define __FUNCT__ "DMPlexGetDepthLabel" 2688 /*@ 2689 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 2690 2691 Not Collective 2692 2693 Input Parameter: 2694 . dm - The DMPlex object 2695 2696 Output Parameter: 2697 . depthLabel - The DMLabel recording point depth 2698 2699 Level: developer 2700 2701 .keywords: mesh, points 2702 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2703 @*/ 2704 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 2705 { 2706 PetscErrorCode ierr; 2707 2708 PetscFunctionBegin; 2709 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2710 PetscValidPointer(depthLabel, 2); 2711 if (!dm->depthLabel) {ierr = DMGetLabel(dm, "depth", &dm->depthLabel);CHKERRQ(ierr);} 2712 *depthLabel = dm->depthLabel; 2713 PetscFunctionReturn(0); 2714 } 2715 2716 #undef __FUNCT__ 2717 #define __FUNCT__ "DMPlexGetDepth" 2718 /*@ 2719 DMPlexGetDepth - Get the depth of the DAG representing this mesh 2720 2721 Not Collective 2722 2723 Input Parameter: 2724 . dm - The DMPlex object 2725 2726 Output Parameter: 2727 . depth - The number of strata (breadth first levels) in the DAG 2728 2729 Level: developer 2730 2731 .keywords: mesh, points 2732 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2733 @*/ 2734 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 2735 { 2736 DMLabel label; 2737 PetscInt d = 0; 2738 PetscErrorCode ierr; 2739 2740 PetscFunctionBegin; 2741 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2742 PetscValidPointer(depth, 2); 2743 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2744 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 2745 *depth = d-1; 2746 PetscFunctionReturn(0); 2747 } 2748 2749 #undef __FUNCT__ 2750 #define __FUNCT__ "DMPlexGetDepthStratum" 2751 /*@ 2752 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 2753 2754 Not Collective 2755 2756 Input Parameters: 2757 + dm - The DMPlex object 2758 - stratumValue - The requested depth 2759 2760 Output Parameters: 2761 + start - The first point at this depth 2762 - end - One beyond the last point at this depth 2763 2764 Level: developer 2765 2766 .keywords: mesh, points 2767 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 2768 @*/ 2769 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2770 { 2771 DMLabel label; 2772 PetscInt pStart, pEnd; 2773 PetscErrorCode ierr; 2774 2775 PetscFunctionBegin; 2776 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2777 if (start) {PetscValidPointer(start, 3); *start = 0;} 2778 if (end) {PetscValidPointer(end, 4); *end = 0;} 2779 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2780 if (pStart == pEnd) PetscFunctionReturn(0); 2781 if (stratumValue < 0) { 2782 if (start) *start = pStart; 2783 if (end) *end = pEnd; 2784 PetscFunctionReturn(0); 2785 } 2786 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2787 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 2788 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 2789 PetscFunctionReturn(0); 2790 } 2791 2792 #undef __FUNCT__ 2793 #define __FUNCT__ "DMPlexGetHeightStratum" 2794 /*@ 2795 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 2796 2797 Not Collective 2798 2799 Input Parameters: 2800 + dm - The DMPlex object 2801 - stratumValue - The requested height 2802 2803 Output Parameters: 2804 + start - The first point at this height 2805 - end - One beyond the last point at this height 2806 2807 Level: developer 2808 2809 .keywords: mesh, points 2810 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 2811 @*/ 2812 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2813 { 2814 DMLabel label; 2815 PetscInt depth, pStart, pEnd; 2816 PetscErrorCode ierr; 2817 2818 PetscFunctionBegin; 2819 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2820 if (start) {PetscValidPointer(start, 3); *start = 0;} 2821 if (end) {PetscValidPointer(end, 4); *end = 0;} 2822 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2823 if (pStart == pEnd) PetscFunctionReturn(0); 2824 if (stratumValue < 0) { 2825 if (start) *start = pStart; 2826 if (end) *end = pEnd; 2827 PetscFunctionReturn(0); 2828 } 2829 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2830 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 2831 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 2832 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 2833 PetscFunctionReturn(0); 2834 } 2835 2836 #undef __FUNCT__ 2837 #define __FUNCT__ "DMPlexCreateSectionInitial" 2838 /* Set the number of dof on each point and separate by fields */ 2839 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 2840 { 2841 PetscInt *pMax; 2842 PetscInt depth, pStart = 0, pEnd = 0; 2843 PetscInt Nf, p, d, dep, f; 2844 PetscBool *isFE; 2845 PetscErrorCode ierr; 2846 2847 PetscFunctionBegin; 2848 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 2849 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 2850 for (f = 0; f < numFields; ++f) { 2851 PetscObject obj; 2852 PetscClassId id; 2853 2854 isFE[f] = PETSC_FALSE; 2855 if (f >= Nf) continue; 2856 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 2857 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 2858 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 2859 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 2860 } 2861 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2862 if (numFields > 0) { 2863 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 2864 if (numComp) { 2865 for (f = 0; f < numFields; ++f) { 2866 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 2867 } 2868 } 2869 } 2870 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2871 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 2872 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2873 ierr = PetscMalloc1(depth+1,&pMax);CHKERRQ(ierr); 2874 ierr = DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 2875 for (dep = 0; dep <= depth; ++dep) { 2876 d = dim == depth ? dep : (!dep ? 0 : dim); 2877 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 2878 pMax[dep] = pMax[dep] < 0 ? pEnd : pMax[dep]; 2879 for (p = pStart; p < pEnd; ++p) { 2880 PetscInt tot = 0; 2881 2882 for (f = 0; f < numFields; ++f) { 2883 if (isFE[f] && p >= pMax[dep]) continue; 2884 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 2885 tot += numDof[f*(dim+1)+d]; 2886 } 2887 ierr = PetscSectionSetDof(*section, p, tot);CHKERRQ(ierr); 2888 } 2889 } 2890 ierr = PetscFree(pMax);CHKERRQ(ierr); 2891 ierr = PetscFree(isFE);CHKERRQ(ierr); 2892 PetscFunctionReturn(0); 2893 } 2894 2895 #undef __FUNCT__ 2896 #define __FUNCT__ "DMPlexCreateSectionBCDof" 2897 /* Set the number of dof on each point and separate by fields 2898 If bcComps is NULL or the IS is NULL, constrain every dof on the point 2899 */ 2900 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 2901 { 2902 PetscInt numFields; 2903 PetscInt bc; 2904 PetscSection aSec; 2905 PetscErrorCode ierr; 2906 2907 PetscFunctionBegin; 2908 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2909 for (bc = 0; bc < numBC; ++bc) { 2910 PetscInt field = 0; 2911 const PetscInt *comp; 2912 const PetscInt *idx; 2913 PetscInt Nc = -1, n, i; 2914 2915 if (numFields) field = bcField[bc]; 2916 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 2917 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2918 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 2919 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2920 for (i = 0; i < n; ++i) { 2921 const PetscInt p = idx[i]; 2922 PetscInt numConst; 2923 2924 if (numFields) { 2925 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 2926 } else { 2927 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 2928 } 2929 /* If Nc < 0, constrain every dof on the point */ 2930 if (Nc > 0) numConst = PetscMin(numConst, Nc); 2931 if (numFields) {ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);} 2932 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 2933 } 2934 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2935 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2936 } 2937 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 2938 if (aSec) { 2939 PetscInt aStart, aEnd, a; 2940 2941 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 2942 for (a = aStart; a < aEnd; a++) { 2943 PetscInt dof, f; 2944 2945 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 2946 if (dof) { 2947 /* if there are point-to-point constraints, then all dofs are constrained */ 2948 ierr = PetscSectionGetDof(section, a, &dof);CHKERRQ(ierr); 2949 ierr = PetscSectionSetConstraintDof(section, a, dof);CHKERRQ(ierr); 2950 for (f = 0; f < numFields; f++) { 2951 ierr = PetscSectionGetFieldDof(section, a, f, &dof);CHKERRQ(ierr); 2952 ierr = PetscSectionSetFieldConstraintDof(section, a, f, dof);CHKERRQ(ierr); 2953 } 2954 } 2955 } 2956 } 2957 PetscFunctionReturn(0); 2958 } 2959 2960 #undef __FUNCT__ 2961 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 2962 /* Set the constrained field indices on each point 2963 If bcComps is NULL or the IS is NULL, constrain every dof on the point 2964 */ 2965 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 2966 { 2967 PetscSection aSec; 2968 PetscInt *indices; 2969 PetscInt numFields, maxDof, pStart, pEnd, p, bc, f, d; 2970 PetscErrorCode ierr; 2971 2972 PetscFunctionBegin; 2973 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2974 if (!numFields) PetscFunctionReturn(0); 2975 /* Initialize all field indices to -1 */ 2976 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 2977 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 2978 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 2979 for (d = 0; d < maxDof; ++d) indices[d] = -1; 2980 for (p = pStart; p < pEnd; ++p) for (f = 0; f < numFields; ++f) {ierr = PetscSectionSetFieldConstraintIndices(section, p, f, indices);CHKERRQ(ierr);} 2981 /* Handle BC constraints */ 2982 for (bc = 0; bc < numBC; ++bc) { 2983 const PetscInt field = bcField[bc]; 2984 const PetscInt *comp, *idx; 2985 PetscInt Nc = -1, n, i; 2986 2987 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 2988 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2989 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 2990 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2991 for (i = 0; i < n; ++i) { 2992 const PetscInt p = idx[i]; 2993 const PetscInt *find; 2994 PetscInt fcdof, c; 2995 2996 ierr = PetscSectionGetFieldConstraintDof(section, p, field, &fcdof);CHKERRQ(ierr); 2997 if (Nc < 0) { 2998 for (d = 0; d < fcdof; ++d) indices[d] = d; 2999 } else { 3000 ierr = PetscSectionGetFieldConstraintIndices(section, p, field, &find);CHKERRQ(ierr); 3001 for (d = 0; d < fcdof; ++d) {if (find[d] < 0) break; indices[d] = find[d];} 3002 for (c = 0; c < Nc; ++c) indices[d+c] = comp[c]; 3003 ierr = PetscSortInt(d+Nc, indices);CHKERRQ(ierr); 3004 for (c = d+Nc; c < fcdof; ++c) indices[c] = -1; 3005 } 3006 ierr = PetscSectionSetFieldConstraintIndices(section, p, field, indices);CHKERRQ(ierr); 3007 } 3008 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3009 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3010 } 3011 /* Handle anchors */ 3012 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3013 if (aSec) { 3014 PetscInt aStart, aEnd, a; 3015 3016 for (d = 0; d < maxDof; ++d) indices[d] = d; 3017 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3018 for (a = aStart; a < aEnd; a++) { 3019 PetscInt dof, fdof, f; 3020 3021 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3022 if (dof) { 3023 /* if there are point-to-point constraints, then all dofs are constrained */ 3024 for (f = 0; f < numFields; f++) { 3025 ierr = PetscSectionGetFieldDof(section, a, f, &fdof);CHKERRQ(ierr); 3026 ierr = PetscSectionSetFieldConstraintIndices(section, a, f, indices);CHKERRQ(ierr); 3027 } 3028 } 3029 } 3030 } 3031 ierr = PetscFree(indices);CHKERRQ(ierr); 3032 PetscFunctionReturn(0); 3033 } 3034 3035 #undef __FUNCT__ 3036 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 3037 /* Set the constrained indices on each point */ 3038 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 3039 { 3040 PetscInt *indices; 3041 PetscInt numFields, maxDof, pStart, pEnd, p, f, d; 3042 PetscErrorCode ierr; 3043 3044 PetscFunctionBegin; 3045 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3046 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3047 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3048 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3049 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3050 for (p = pStart; p < pEnd; ++p) { 3051 PetscInt cdof, d; 3052 3053 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 3054 if (cdof) { 3055 if (numFields) { 3056 PetscInt numConst = 0, foff = 0; 3057 3058 for (f = 0; f < numFields; ++f) { 3059 const PetscInt *find; 3060 PetscInt fcdof, fdof; 3061 3062 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 3063 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 3064 /* Change constraint numbering from field component to local dof number */ 3065 ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &find);CHKERRQ(ierr); 3066 for (d = 0; d < fcdof; ++d) indices[numConst+d] = find[d] + foff; 3067 numConst += fcdof; 3068 foff += fdof; 3069 } 3070 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 3071 } else { 3072 for (d = 0; d < cdof; ++d) indices[d] = d; 3073 } 3074 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 3075 } 3076 } 3077 ierr = PetscFree(indices);CHKERRQ(ierr); 3078 PetscFunctionReturn(0); 3079 } 3080 3081 #undef __FUNCT__ 3082 #define __FUNCT__ "DMPlexCreateSection" 3083 /*@C 3084 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 3085 3086 Not Collective 3087 3088 Input Parameters: 3089 + dm - The DMPlex object 3090 . dim - The spatial dimension of the problem 3091 . numFields - The number of fields in the problem 3092 . numComp - An array of size numFields that holds the number of components for each field 3093 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 3094 . numBC - The number of boundary conditions 3095 . bcField - An array of size numBC giving the field number for each boundry condition 3096 . bcComps - [Optional] An array of size numBC giving an IS holding the field components to which each boundary condition applies 3097 . bcPoints - An array of size numBC giving an IS holding the Plex points to which each boundary condition applies 3098 - perm - Optional permutation of the chart, or NULL 3099 3100 Output Parameter: 3101 . section - The PetscSection object 3102 3103 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 3104 number of dof for field 0 on each edge. 3105 3106 The chart permutation is the same one set using PetscSectionSetPermutation() 3107 3108 Level: developer 3109 3110 Fortran Notes: 3111 A Fortran 90 version is available as DMPlexCreateSectionF90() 3112 3113 .keywords: mesh, elements 3114 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 3115 @*/ 3116 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) 3117 { 3118 PetscSection aSec; 3119 PetscErrorCode ierr; 3120 3121 PetscFunctionBegin; 3122 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 3123 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3124 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 3125 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3126 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 3127 if (numBC || aSec) { 3128 ierr = DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3129 ierr = DMPlexCreateSectionBCIndices(dm, *section);CHKERRQ(ierr); 3130 } 3131 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 3132 PetscFunctionReturn(0); 3133 } 3134 3135 #undef __FUNCT__ 3136 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 3137 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 3138 { 3139 PetscSection section, s; 3140 Mat m; 3141 PetscInt maxHeight; 3142 PetscErrorCode ierr; 3143 3144 PetscFunctionBegin; 3145 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3146 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 3147 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 3148 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3149 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 3150 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3151 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 3152 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 3153 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 3154 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 3155 ierr = MatDestroy(&m);CHKERRQ(ierr); 3156 PetscFunctionReturn(0); 3157 } 3158 3159 #undef __FUNCT__ 3160 #define __FUNCT__ "DMPlexGetConeSection" 3161 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3162 { 3163 DM_Plex *mesh = (DM_Plex*) dm->data; 3164 3165 PetscFunctionBegin; 3166 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3167 if (section) *section = mesh->coneSection; 3168 PetscFunctionReturn(0); 3169 } 3170 3171 #undef __FUNCT__ 3172 #define __FUNCT__ "DMPlexGetSupportSection" 3173 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3174 { 3175 DM_Plex *mesh = (DM_Plex*) dm->data; 3176 3177 PetscFunctionBegin; 3178 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3179 if (section) *section = mesh->supportSection; 3180 PetscFunctionReturn(0); 3181 } 3182 3183 #undef __FUNCT__ 3184 #define __FUNCT__ "DMPlexGetCones" 3185 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3186 { 3187 DM_Plex *mesh = (DM_Plex*) dm->data; 3188 3189 PetscFunctionBegin; 3190 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3191 if (cones) *cones = mesh->cones; 3192 PetscFunctionReturn(0); 3193 } 3194 3195 #undef __FUNCT__ 3196 #define __FUNCT__ "DMPlexGetConeOrientations" 3197 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3198 { 3199 DM_Plex *mesh = (DM_Plex*) dm->data; 3200 3201 PetscFunctionBegin; 3202 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3203 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3204 PetscFunctionReturn(0); 3205 } 3206 3207 /******************************** FEM Support **********************************/ 3208 3209 #undef __FUNCT__ 3210 #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static" 3211 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3212 { 3213 PetscScalar *array, *vArray; 3214 const PetscInt *cone, *coneO; 3215 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3216 PetscErrorCode ierr; 3217 3218 PetscFunctionBeginHot; 3219 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3220 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3221 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3222 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3223 if (!values || !*values) { 3224 if ((point >= pStart) && (point < pEnd)) { 3225 PetscInt dof; 3226 3227 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3228 size += dof; 3229 } 3230 for (p = 0; p < numPoints; ++p) { 3231 const PetscInt cp = cone[p]; 3232 PetscInt dof; 3233 3234 if ((cp < pStart) || (cp >= pEnd)) continue; 3235 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3236 size += dof; 3237 } 3238 if (!values) { 3239 if (csize) *csize = size; 3240 PetscFunctionReturn(0); 3241 } 3242 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 3243 } else { 3244 array = *values; 3245 } 3246 size = 0; 3247 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3248 if ((point >= pStart) && (point < pEnd)) { 3249 PetscInt dof, off, d; 3250 PetscScalar *varr; 3251 3252 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3253 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3254 varr = &vArray[off]; 3255 for (d = 0; d < dof; ++d, ++offset) { 3256 array[offset] = varr[d]; 3257 } 3258 size += dof; 3259 } 3260 for (p = 0; p < numPoints; ++p) { 3261 const PetscInt cp = cone[p]; 3262 PetscInt o = coneO[p]; 3263 PetscInt dof, off, d; 3264 PetscScalar *varr; 3265 3266 if ((cp < pStart) || (cp >= pEnd)) continue; 3267 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3268 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3269 varr = &vArray[off]; 3270 if (o >= 0) { 3271 for (d = 0; d < dof; ++d, ++offset) { 3272 array[offset] = varr[d]; 3273 } 3274 } else { 3275 for (d = dof-1; d >= 0; --d, ++offset) { 3276 array[offset] = varr[d]; 3277 } 3278 } 3279 size += dof; 3280 } 3281 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3282 if (!*values) { 3283 if (csize) *csize = size; 3284 *values = array; 3285 } else { 3286 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3287 *csize = size; 3288 } 3289 PetscFunctionReturn(0); 3290 } 3291 3292 #undef __FUNCT__ 3293 #define __FUNCT__ "DMPlexVecGetClosure_Static" 3294 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3295 { 3296 PetscInt offset = 0, p; 3297 PetscErrorCode ierr; 3298 3299 PetscFunctionBeginHot; 3300 *size = 0; 3301 for (p = 0; p < numPoints*2; p += 2) { 3302 const PetscInt point = points[p]; 3303 const PetscInt o = points[p+1]; 3304 PetscInt dof, off, d; 3305 const PetscScalar *varr; 3306 3307 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3308 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3309 varr = &vArray[off]; 3310 if (o >= 0) { 3311 for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 3312 } else { 3313 for (d = dof-1; d >= 0; --d, ++offset) array[offset] = varr[d]; 3314 } 3315 } 3316 *size = offset; 3317 PetscFunctionReturn(0); 3318 } 3319 3320 #undef __FUNCT__ 3321 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 3322 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3323 { 3324 PetscInt offset = 0, f; 3325 PetscErrorCode ierr; 3326 3327 PetscFunctionBeginHot; 3328 *size = 0; 3329 for (f = 0; f < numFields; ++f) { 3330 PetscInt fcomp, p; 3331 3332 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3333 for (p = 0; p < numPoints*2; p += 2) { 3334 const PetscInt point = points[p]; 3335 const PetscInt o = points[p+1]; 3336 PetscInt fdof, foff, d, c; 3337 const PetscScalar *varr; 3338 3339 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3340 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3341 varr = &vArray[foff]; 3342 if (o >= 0) { 3343 for (d = 0; d < fdof; ++d, ++offset) array[offset] = varr[d]; 3344 } else { 3345 for (d = fdof/fcomp-1; d >= 0; --d) { 3346 for (c = 0; c < fcomp; ++c, ++offset) { 3347 array[offset] = varr[d*fcomp+c]; 3348 } 3349 } 3350 } 3351 } 3352 } 3353 *size = offset; 3354 PetscFunctionReturn(0); 3355 } 3356 3357 #undef __FUNCT__ 3358 #define __FUNCT__ "DMPlexVecGetClosure" 3359 /*@C 3360 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 3361 3362 Not collective 3363 3364 Input Parameters: 3365 + dm - The DM 3366 . section - The section describing the layout in v, or NULL to use the default section 3367 . v - The local vector 3368 - point - The sieve point in the DM 3369 3370 Output Parameters: 3371 + csize - The number of values in the closure, or NULL 3372 - values - The array of values, which is a borrowed array and should not be freed 3373 3374 Fortran Notes: 3375 Since it returns an array, this routine is only available in Fortran 90, and you must 3376 include petsc.h90 in your code. 3377 3378 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3379 3380 Level: intermediate 3381 3382 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3383 @*/ 3384 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3385 { 3386 PetscSection clSection; 3387 IS clPoints; 3388 PetscScalar *array, *vArray; 3389 PetscInt *points = NULL; 3390 const PetscInt *clp; 3391 PetscInt depth, numFields, numPoints, size; 3392 PetscErrorCode ierr; 3393 3394 PetscFunctionBeginHot; 3395 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3396 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3397 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3398 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3399 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3400 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3401 if (depth == 1 && numFields < 2) { 3402 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 3403 PetscFunctionReturn(0); 3404 } 3405 /* Get points */ 3406 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3407 if (!clPoints) { 3408 PetscInt pStart, pEnd, p, q; 3409 3410 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3411 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3412 /* Compress out points not in the section */ 3413 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3414 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3415 points[q*2] = points[p]; 3416 points[q*2+1] = points[p+1]; 3417 ++q; 3418 } 3419 } 3420 numPoints = q; 3421 } else { 3422 PetscInt dof, off; 3423 3424 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3425 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3426 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3427 numPoints = dof/2; 3428 points = (PetscInt *) &clp[off]; 3429 } 3430 /* Get array */ 3431 if (!values || !*values) { 3432 PetscInt asize = 0, dof, p; 3433 3434 for (p = 0; p < numPoints*2; p += 2) { 3435 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3436 asize += dof; 3437 } 3438 if (!values) { 3439 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3440 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3441 if (csize) *csize = asize; 3442 PetscFunctionReturn(0); 3443 } 3444 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 3445 } else { 3446 array = *values; 3447 } 3448 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3449 /* Get values */ 3450 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, vArray, &size, array);CHKERRQ(ierr);} 3451 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, vArray, &size, array);CHKERRQ(ierr);} 3452 /* Cleanup points */ 3453 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3454 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3455 /* Cleanup array */ 3456 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3457 if (!*values) { 3458 if (csize) *csize = size; 3459 *values = array; 3460 } else { 3461 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3462 *csize = size; 3463 } 3464 PetscFunctionReturn(0); 3465 } 3466 3467 #undef __FUNCT__ 3468 #define __FUNCT__ "DMPlexVecRestoreClosure" 3469 /*@C 3470 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 3471 3472 Not collective 3473 3474 Input Parameters: 3475 + dm - The DM 3476 . section - The section describing the layout in v, or NULL to use the default section 3477 . v - The local vector 3478 . point - The sieve point in the DM 3479 . csize - The number of values in the closure, or NULL 3480 - values - The array of values, which is a borrowed array and should not be freed 3481 3482 Fortran Notes: 3483 Since it returns an array, this routine is only available in Fortran 90, and you must 3484 include petsc.h90 in your code. 3485 3486 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3487 3488 Level: intermediate 3489 3490 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3491 @*/ 3492 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3493 { 3494 PetscInt size = 0; 3495 PetscErrorCode ierr; 3496 3497 PetscFunctionBegin; 3498 /* Should work without recalculating size */ 3499 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 3500 PetscFunctionReturn(0); 3501 } 3502 3503 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 3504 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 3505 3506 #undef __FUNCT__ 3507 #define __FUNCT__ "updatePoint_private" 3508 PETSC_STATIC_INLINE PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 3509 { 3510 PetscInt cdof; /* The number of constraints on this point */ 3511 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3512 PetscScalar *a; 3513 PetscInt off, cind = 0, k; 3514 PetscErrorCode ierr; 3515 3516 PetscFunctionBegin; 3517 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3518 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3519 a = &array[off]; 3520 if (!cdof || setBC) { 3521 if (orientation >= 0) { 3522 for (k = 0; k < dof; ++k) { 3523 fuse(&a[k], values[k]); 3524 } 3525 } else { 3526 for (k = 0; k < dof; ++k) { 3527 fuse(&a[k], values[dof-k-1]); 3528 } 3529 } 3530 } else { 3531 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3532 if (orientation >= 0) { 3533 for (k = 0; k < dof; ++k) { 3534 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3535 fuse(&a[k], values[k]); 3536 } 3537 } else { 3538 for (k = 0; k < dof; ++k) { 3539 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3540 fuse(&a[k], values[dof-k-1]); 3541 } 3542 } 3543 } 3544 PetscFunctionReturn(0); 3545 } 3546 3547 #undef __FUNCT__ 3548 #define __FUNCT__ "updatePointBC_private" 3549 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 3550 { 3551 PetscInt cdof; /* The number of constraints on this point */ 3552 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3553 PetscScalar *a; 3554 PetscInt off, cind = 0, k; 3555 PetscErrorCode ierr; 3556 3557 PetscFunctionBegin; 3558 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3559 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3560 a = &array[off]; 3561 if (cdof) { 3562 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3563 if (orientation >= 0) { 3564 for (k = 0; k < dof; ++k) { 3565 if ((cind < cdof) && (k == cdofs[cind])) { 3566 fuse(&a[k], values[k]); 3567 ++cind; 3568 } 3569 } 3570 } else { 3571 for (k = 0; k < dof; ++k) { 3572 if ((cind < cdof) && (k == cdofs[cind])) { 3573 fuse(&a[k], values[dof-k-1]); 3574 ++cind; 3575 } 3576 } 3577 } 3578 } 3579 PetscFunctionReturn(0); 3580 } 3581 3582 #undef __FUNCT__ 3583 #define __FUNCT__ "updatePointFields_private" 3584 PETSC_STATIC_INLINE PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 3585 { 3586 PetscScalar *a; 3587 PetscInt fdof, foff, fcdof, foffset = *offset; 3588 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3589 PetscInt cind = 0, k, c; 3590 PetscErrorCode ierr; 3591 3592 PetscFunctionBegin; 3593 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3594 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3595 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3596 a = &array[foff]; 3597 if (!fcdof || setBC) { 3598 if (o >= 0) { 3599 for (k = 0; k < fdof; ++k) fuse(&a[k], values[foffset+k]); 3600 } else { 3601 for (k = fdof/fcomp-1; k >= 0; --k) { 3602 for (c = 0; c < fcomp; ++c) { 3603 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3604 } 3605 } 3606 } 3607 } else { 3608 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3609 if (o >= 0) { 3610 for (k = 0; k < fdof; ++k) { 3611 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 3612 fuse(&a[k], values[foffset+k]); 3613 } 3614 } else { 3615 for (k = fdof/fcomp-1; k >= 0; --k) { 3616 for (c = 0; c < fcomp; ++c) { 3617 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 3618 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3619 } 3620 } 3621 } 3622 } 3623 *offset += fdof; 3624 PetscFunctionReturn(0); 3625 } 3626 3627 #undef __FUNCT__ 3628 #define __FUNCT__ "updatePointFieldsBC_private" 3629 PETSC_STATIC_INLINE PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 3630 { 3631 PetscScalar *a; 3632 PetscInt fdof, foff, fcdof, foffset = *offset; 3633 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3634 PetscInt cind = 0, k, c; 3635 PetscErrorCode ierr; 3636 3637 PetscFunctionBegin; 3638 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3639 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3640 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3641 a = &array[foff]; 3642 if (fcdof) { 3643 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3644 if (o >= 0) { 3645 for (k = 0; k < fdof; ++k) { 3646 if ((cind < fcdof) && (k == fcdofs[cind])) { 3647 fuse(&a[k], values[foffset+k]); 3648 ++cind; 3649 } 3650 } 3651 } else { 3652 for (k = fdof/fcomp-1; k >= 0; --k) { 3653 for (c = 0; c < fcomp; ++c) { 3654 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 3655 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3656 ++cind; 3657 } 3658 } 3659 } 3660 } 3661 } 3662 *offset += fdof; 3663 PetscFunctionReturn(0); 3664 } 3665 3666 #undef __FUNCT__ 3667 #define __FUNCT__ "DMPlexVecSetClosure_Static" 3668 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3669 { 3670 PetscScalar *array; 3671 const PetscInt *cone, *coneO; 3672 PetscInt pStart, pEnd, p, numPoints, off, dof; 3673 PetscErrorCode ierr; 3674 3675 PetscFunctionBeginHot; 3676 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3677 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3678 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3679 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3680 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3681 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 3682 const PetscInt cp = !p ? point : cone[p-1]; 3683 const PetscInt o = !p ? 0 : coneO[p-1]; 3684 3685 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 3686 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3687 /* ADD_VALUES */ 3688 { 3689 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3690 PetscScalar *a; 3691 PetscInt cdof, coff, cind = 0, k; 3692 3693 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 3694 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 3695 a = &array[coff]; 3696 if (!cdof) { 3697 if (o >= 0) { 3698 for (k = 0; k < dof; ++k) { 3699 a[k] += values[off+k]; 3700 } 3701 } else { 3702 for (k = 0; k < dof; ++k) { 3703 a[k] += values[off+dof-k-1]; 3704 } 3705 } 3706 } else { 3707 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 3708 if (o >= 0) { 3709 for (k = 0; k < dof; ++k) { 3710 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3711 a[k] += values[off+k]; 3712 } 3713 } else { 3714 for (k = 0; k < dof; ++k) { 3715 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3716 a[k] += values[off+dof-k-1]; 3717 } 3718 } 3719 } 3720 } 3721 } 3722 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3723 PetscFunctionReturn(0); 3724 } 3725 3726 #undef __FUNCT__ 3727 #define __FUNCT__ "DMPlexVecSetClosure" 3728 /*@C 3729 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 3730 3731 Not collective 3732 3733 Input Parameters: 3734 + dm - The DM 3735 . section - The section describing the layout in v, or NULL to use the default section 3736 . v - The local vector 3737 . point - The sieve point in the DM 3738 . values - The array of values 3739 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 3740 3741 Fortran Notes: 3742 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3743 3744 Level: intermediate 3745 3746 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 3747 @*/ 3748 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3749 { 3750 PetscSection clSection; 3751 IS clPoints; 3752 PetscScalar *array; 3753 PetscInt *points = NULL; 3754 const PetscInt *clp; 3755 PetscInt depth, numFields, numPoints, p; 3756 PetscErrorCode ierr; 3757 3758 PetscFunctionBeginHot; 3759 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3760 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3761 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3762 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3763 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3764 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3765 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 3766 ierr = DMPlexVecSetClosure_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 3767 PetscFunctionReturn(0); 3768 } 3769 /* Get points */ 3770 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3771 if (!clPoints) { 3772 PetscInt pStart, pEnd, q; 3773 3774 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3775 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3776 /* Compress out points not in the section */ 3777 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3778 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3779 points[q*2] = points[p]; 3780 points[q*2+1] = points[p+1]; 3781 ++q; 3782 } 3783 } 3784 numPoints = q; 3785 } else { 3786 PetscInt dof, off; 3787 3788 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3789 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3790 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3791 numPoints = dof/2; 3792 points = (PetscInt *) &clp[off]; 3793 } 3794 /* Get array */ 3795 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3796 /* Get values */ 3797 if (numFields > 0) { 3798 PetscInt offset = 0, fcomp, f; 3799 for (f = 0; f < numFields; ++f) { 3800 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3801 switch (mode) { 3802 case INSERT_VALUES: 3803 for (p = 0; p < numPoints*2; p += 2) { 3804 const PetscInt point = points[p]; 3805 const PetscInt o = points[p+1]; 3806 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 3807 } break; 3808 case INSERT_ALL_VALUES: 3809 for (p = 0; p < numPoints*2; p += 2) { 3810 const PetscInt point = points[p]; 3811 const PetscInt o = points[p+1]; 3812 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 3813 } break; 3814 case INSERT_BC_VALUES: 3815 for (p = 0; p < numPoints*2; p += 2) { 3816 const PetscInt point = points[p]; 3817 const PetscInt o = points[p+1]; 3818 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3819 } break; 3820 case ADD_VALUES: 3821 for (p = 0; p < numPoints*2; p += 2) { 3822 const PetscInt point = points[p]; 3823 const PetscInt o = points[p+1]; 3824 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3825 } break; 3826 case ADD_ALL_VALUES: 3827 for (p = 0; p < numPoints*2; p += 2) { 3828 const PetscInt point = points[p]; 3829 const PetscInt o = points[p+1]; 3830 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3831 } break; 3832 case ADD_BC_VALUES: 3833 for (p = 0; p < numPoints*2; p += 2) { 3834 const PetscInt point = points[p]; 3835 const PetscInt o = points[p+1]; 3836 updatePointFieldsBC_private(section, point, o, f, fcomp, add, values, &offset, array); 3837 } break; 3838 default: 3839 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3840 } 3841 } 3842 } else { 3843 PetscInt dof, off; 3844 3845 switch (mode) { 3846 case INSERT_VALUES: 3847 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3848 PetscInt o = points[p+1]; 3849 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3850 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 3851 } break; 3852 case INSERT_ALL_VALUES: 3853 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3854 PetscInt o = points[p+1]; 3855 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3856 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 3857 } break; 3858 case INSERT_BC_VALUES: 3859 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3860 PetscInt o = points[p+1]; 3861 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3862 updatePointBC_private(section, points[p], dof, insert, o, &values[off], array); 3863 } break; 3864 case ADD_VALUES: 3865 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3866 PetscInt o = points[p+1]; 3867 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3868 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 3869 } break; 3870 case ADD_ALL_VALUES: 3871 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3872 PetscInt o = points[p+1]; 3873 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3874 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 3875 } break; 3876 case ADD_BC_VALUES: 3877 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3878 PetscInt o = points[p+1]; 3879 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3880 updatePointBC_private(section, points[p], dof, add, o, &values[off], array); 3881 } break; 3882 default: 3883 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3884 } 3885 } 3886 /* Cleanup points */ 3887 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3888 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3889 /* Cleanup array */ 3890 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3891 PetscFunctionReturn(0); 3892 } 3893 3894 #undef __FUNCT__ 3895 #define __FUNCT__ "DMPlexVecSetFieldClosure_Internal" 3896 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, const PetscScalar values[], InsertMode mode) 3897 { 3898 PetscSection clSection; 3899 IS clPoints; 3900 PetscScalar *array; 3901 PetscInt *points = NULL; 3902 const PetscInt *clp; 3903 PetscInt numFields, numPoints, p; 3904 PetscInt offset = 0, fcomp, f; 3905 PetscErrorCode ierr; 3906 3907 PetscFunctionBeginHot; 3908 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3909 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3910 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3911 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3912 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3913 /* Get points */ 3914 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3915 if (!clPoints) { 3916 PetscInt pStart, pEnd, q; 3917 3918 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3919 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3920 /* Compress out points not in the section */ 3921 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3922 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3923 points[q*2] = points[p]; 3924 points[q*2+1] = points[p+1]; 3925 ++q; 3926 } 3927 } 3928 numPoints = q; 3929 } else { 3930 PetscInt dof, off; 3931 3932 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3933 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3934 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3935 numPoints = dof/2; 3936 points = (PetscInt *) &clp[off]; 3937 } 3938 /* Get array */ 3939 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3940 /* Get values */ 3941 for (f = 0; f < numFields; ++f) { 3942 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3943 if (!fieldActive[f]) { 3944 for (p = 0; p < numPoints*2; p += 2) { 3945 PetscInt fdof; 3946 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 3947 offset += fdof; 3948 } 3949 continue; 3950 } 3951 switch (mode) { 3952 case INSERT_VALUES: 3953 for (p = 0; p < numPoints*2; p += 2) { 3954 const PetscInt point = points[p]; 3955 const PetscInt o = points[p+1]; 3956 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 3957 } break; 3958 case INSERT_ALL_VALUES: 3959 for (p = 0; p < numPoints*2; p += 2) { 3960 const PetscInt point = points[p]; 3961 const PetscInt o = points[p+1]; 3962 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 3963 } break; 3964 case INSERT_BC_VALUES: 3965 for (p = 0; p < numPoints*2; p += 2) { 3966 const PetscInt point = points[p]; 3967 const PetscInt o = points[p+1]; 3968 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3969 } break; 3970 case ADD_VALUES: 3971 for (p = 0; p < numPoints*2; p += 2) { 3972 const PetscInt point = points[p]; 3973 const PetscInt o = points[p+1]; 3974 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3975 } break; 3976 case ADD_ALL_VALUES: 3977 for (p = 0; p < numPoints*2; p += 2) { 3978 const PetscInt point = points[p]; 3979 const PetscInt o = points[p+1]; 3980 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3981 } break; 3982 default: 3983 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3984 } 3985 } 3986 /* Cleanup points */ 3987 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3988 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3989 /* Cleanup array */ 3990 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3991 PetscFunctionReturn(0); 3992 } 3993 3994 #undef __FUNCT__ 3995 #define __FUNCT__ "DMPlexPrintMatSetValues" 3996 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 3997 { 3998 PetscMPIInt rank; 3999 PetscInt i, j; 4000 PetscErrorCode ierr; 4001 4002 PetscFunctionBegin; 4003 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4004 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 4005 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4006 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4007 numCIndices = numCIndices ? numCIndices : numRIndices; 4008 for (i = 0; i < numRIndices; i++) { 4009 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4010 for (j = 0; j < numCIndices; j++) { 4011 #if defined(PETSC_USE_COMPLEX) 4012 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4013 #else 4014 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4015 #endif 4016 } 4017 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4018 } 4019 PetscFunctionReturn(0); 4020 } 4021 4022 #undef __FUNCT__ 4023 #define __FUNCT__ "DMPlexGetIndicesPoint_Internal" 4024 /* . off - The global offset of this point */ 4025 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4026 { 4027 PetscInt dof; /* The number of unknowns on this point */ 4028 PetscInt cdof; /* The number of constraints on this point */ 4029 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4030 PetscInt cind = 0, k; 4031 PetscErrorCode ierr; 4032 4033 PetscFunctionBegin; 4034 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4035 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4036 if (!cdof || setBC) { 4037 if (orientation >= 0) { 4038 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 4039 } else { 4040 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 4041 } 4042 } else { 4043 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4044 if (orientation >= 0) { 4045 for (k = 0; k < dof; ++k) { 4046 if ((cind < cdof) && (k == cdofs[cind])) { 4047 /* Insert check for returning constrained indices */ 4048 indices[*loff+k] = -(off+k+1); 4049 ++cind; 4050 } else { 4051 indices[*loff+k] = off+k-cind; 4052 } 4053 } 4054 } else { 4055 for (k = 0; k < dof; ++k) { 4056 if ((cind < cdof) && (k == cdofs[cind])) { 4057 /* Insert check for returning constrained indices */ 4058 indices[*loff+dof-k-1] = -(off+k+1); 4059 ++cind; 4060 } else { 4061 indices[*loff+dof-k-1] = off+k-cind; 4062 } 4063 } 4064 } 4065 } 4066 *loff += dof; 4067 PetscFunctionReturn(0); 4068 } 4069 4070 #undef __FUNCT__ 4071 #define __FUNCT__ "DMPlexGetIndicesPointFields_Internal" 4072 /* . off - The global offset of this point */ 4073 PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4074 { 4075 PetscInt numFields, foff, f; 4076 PetscErrorCode ierr; 4077 4078 PetscFunctionBegin; 4079 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4080 for (f = 0, foff = 0; f < numFields; ++f) { 4081 PetscInt fdof, fcomp, cfdof; 4082 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4083 PetscInt cind = 0, k, c; 4084 4085 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4086 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4087 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4088 if (!cfdof || setBC) { 4089 if (orientation >= 0) { 4090 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 4091 } else { 4092 for (k = fdof/fcomp-1; k >= 0; --k) { 4093 for (c = 0; c < fcomp; ++c) { 4094 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 4095 } 4096 } 4097 } 4098 } else { 4099 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4100 if (orientation >= 0) { 4101 for (k = 0; k < fdof; ++k) { 4102 if ((cind < cfdof) && (k == fcdofs[cind])) { 4103 indices[foffs[f]+k] = -(off+foff+k+1); 4104 ++cind; 4105 } else { 4106 indices[foffs[f]+k] = off+foff+k-cind; 4107 } 4108 } 4109 } else { 4110 for (k = fdof/fcomp-1; k >= 0; --k) { 4111 for (c = 0; c < fcomp; ++c) { 4112 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 4113 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 4114 ++cind; 4115 } else { 4116 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 4117 } 4118 } 4119 } 4120 } 4121 } 4122 foff += (setBC ? fdof : (fdof - cfdof)); 4123 foffs[f] += fdof; 4124 } 4125 PetscFunctionReturn(0); 4126 } 4127 4128 #undef __FUNCT__ 4129 #define __FUNCT__ "DMPlexAnchorsModifyMat" 4130 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) 4131 { 4132 Mat cMat; 4133 PetscSection aSec, cSec; 4134 IS aIS; 4135 PetscInt aStart = -1, aEnd = -1; 4136 const PetscInt *anchors; 4137 PetscInt numFields, f, p, q, newP = 0; 4138 PetscInt newNumPoints = 0, newNumIndices = 0; 4139 PetscInt *newPoints, *indices, *newIndices; 4140 PetscInt maxAnchor, maxDof; 4141 PetscInt newOffsets[32]; 4142 PetscInt *pointMatOffsets[32]; 4143 PetscInt *newPointOffsets[32]; 4144 PetscScalar *pointMat[32]; 4145 PetscScalar *newValues=NULL,*tmpValues; 4146 PetscBool anyConstrained = PETSC_FALSE; 4147 PetscErrorCode ierr; 4148 4149 PetscFunctionBegin; 4150 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4151 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4152 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4153 4154 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4155 /* if there are point-to-point constraints */ 4156 if (aSec) { 4157 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4158 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 4159 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 4160 /* figure out how many points are going to be in the new element matrix 4161 * (we allow double counting, because it's all just going to be summed 4162 * into the global matrix anyway) */ 4163 for (p = 0; p < 2*numPoints; p+=2) { 4164 PetscInt b = points[p]; 4165 PetscInt bDof = 0, bSecDof; 4166 4167 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4168 if (!bSecDof) { 4169 continue; 4170 } 4171 if (b >= aStart && b < aEnd) { 4172 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4173 } 4174 if (bDof) { 4175 /* this point is constrained */ 4176 /* it is going to be replaced by its anchors */ 4177 PetscInt bOff, q; 4178 4179 anyConstrained = PETSC_TRUE; 4180 newNumPoints += bDof; 4181 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4182 for (q = 0; q < bDof; q++) { 4183 PetscInt a = anchors[bOff + q]; 4184 PetscInt aDof; 4185 4186 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4187 newNumIndices += aDof; 4188 for (f = 0; f < numFields; ++f) { 4189 PetscInt fDof; 4190 4191 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4192 newOffsets[f+1] += fDof; 4193 } 4194 } 4195 } 4196 else { 4197 /* this point is not constrained */ 4198 newNumPoints++; 4199 newNumIndices += bSecDof; 4200 for (f = 0; f < numFields; ++f) { 4201 PetscInt fDof; 4202 4203 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4204 newOffsets[f+1] += fDof; 4205 } 4206 } 4207 } 4208 } 4209 if (!anyConstrained) { 4210 if (outNumPoints) *outNumPoints = 0; 4211 if (outNumIndices) *outNumIndices = 0; 4212 if (outPoints) *outPoints = NULL; 4213 if (outValues) *outValues = NULL; 4214 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4215 PetscFunctionReturn(0); 4216 } 4217 4218 if (outNumPoints) *outNumPoints = newNumPoints; 4219 if (outNumIndices) *outNumIndices = newNumIndices; 4220 4221 for (f = 1; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4222 4223 if (!outPoints && !outValues) { 4224 if (offsets) { 4225 for (f = 0; f <= numFields; f++) { 4226 offsets[f] = newOffsets[f]; 4227 } 4228 } 4229 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4230 PetscFunctionReturn(0); 4231 } 4232 4233 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 4234 4235 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4236 4237 /* workspaces */ 4238 if (numFields) { 4239 for (f = 0; f < numFields; f++) { 4240 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4241 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4242 } 4243 } 4244 else { 4245 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4246 ierr = DMGetWorkArray(dm,numPoints,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4247 } 4248 4249 /* get workspaces for the point-to-point matrices */ 4250 if (numFields) { 4251 PetscInt totalOffset, totalMatOffset; 4252 4253 for (p = 0; p < numPoints; p++) { 4254 PetscInt b = points[2*p]; 4255 PetscInt bDof = 0, bSecDof; 4256 4257 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4258 if (!bSecDof) { 4259 for (f = 0; f < numFields; f++) { 4260 newPointOffsets[f][p + 1] = 0; 4261 pointMatOffsets[f][p + 1] = 0; 4262 } 4263 continue; 4264 } 4265 if (b >= aStart && b < aEnd) { 4266 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4267 } 4268 if (bDof) { 4269 for (f = 0; f < numFields; f++) { 4270 PetscInt fDof, q, bOff, allFDof = 0; 4271 4272 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4273 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4274 for (q = 0; q < bDof; q++) { 4275 PetscInt a = anchors[bOff + q]; 4276 PetscInt aFDof; 4277 4278 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4279 allFDof += aFDof; 4280 } 4281 newPointOffsets[f][p+1] = allFDof; 4282 pointMatOffsets[f][p+1] = fDof * allFDof; 4283 } 4284 } 4285 else { 4286 for (f = 0; f < numFields; f++) { 4287 PetscInt fDof; 4288 4289 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4290 newPointOffsets[f][p+1] = fDof; 4291 pointMatOffsets[f][p+1] = 0; 4292 } 4293 } 4294 } 4295 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 4296 newPointOffsets[f][0] = totalOffset; 4297 pointMatOffsets[f][0] = totalMatOffset; 4298 for (p = 0; p < numPoints; p++) { 4299 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 4300 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 4301 } 4302 totalOffset = newPointOffsets[f][numPoints]; 4303 totalMatOffset = pointMatOffsets[f][numPoints]; 4304 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4305 } 4306 } 4307 else { 4308 for (p = 0; p < numPoints; p++) { 4309 PetscInt b = points[2*p]; 4310 PetscInt bDof = 0, bSecDof; 4311 4312 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4313 if (!bSecDof) { 4314 newPointOffsets[0][p + 1] = 0; 4315 pointMatOffsets[0][p + 1] = 0; 4316 continue; 4317 } 4318 if (b >= aStart && b < aEnd) { 4319 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4320 } 4321 if (bDof) { 4322 PetscInt bOff, q, allDof = 0; 4323 4324 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4325 for (q = 0; q < bDof; q++) { 4326 PetscInt a = anchors[bOff + q], aDof; 4327 4328 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 4329 allDof += aDof; 4330 } 4331 newPointOffsets[0][p+1] = allDof; 4332 pointMatOffsets[0][p+1] = bSecDof * allDof; 4333 } 4334 else { 4335 newPointOffsets[0][p+1] = bSecDof; 4336 pointMatOffsets[0][p+1] = 0; 4337 } 4338 } 4339 newPointOffsets[0][0] = 0; 4340 pointMatOffsets[0][0] = 0; 4341 for (p = 0; p < numPoints; p++) { 4342 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 4343 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 4344 } 4345 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4346 } 4347 4348 /* output arrays */ 4349 ierr = DMGetWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4350 4351 /* get the point-to-point matrices; construct newPoints */ 4352 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 4353 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4354 ierr = DMGetWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4355 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4356 if (numFields) { 4357 for (p = 0, newP = 0; p < numPoints; p++) { 4358 PetscInt b = points[2*p]; 4359 PetscInt o = points[2*p+1]; 4360 PetscInt bDof = 0, bSecDof; 4361 4362 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 4363 if (!bSecDof) { 4364 continue; 4365 } 4366 if (b >= aStart && b < aEnd) { 4367 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4368 } 4369 if (bDof) { 4370 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 4371 4372 fStart[0] = 0; 4373 fEnd[0] = 0; 4374 for (f = 0; f < numFields; f++) { 4375 PetscInt fDof; 4376 4377 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 4378 fStart[f+1] = fStart[f] + fDof; 4379 fEnd[f+1] = fStart[f+1]; 4380 } 4381 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4382 ierr = DMPlexGetIndicesPointFields_Internal(cSec, b, bOff, fEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4383 4384 fAnchorStart[0] = 0; 4385 fAnchorEnd[0] = 0; 4386 for (f = 0; f < numFields; f++) { 4387 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 4388 4389 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 4390 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 4391 } 4392 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4393 for (q = 0; q < bDof; q++) { 4394 PetscInt a = anchors[bOff + q], aOff; 4395 4396 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4397 newPoints[2*(newP + q)] = a; 4398 newPoints[2*(newP + q) + 1] = 0; 4399 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4400 ierr = DMPlexGetIndicesPointFields_Internal(section, a, aOff, fAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4401 } 4402 newP += bDof; 4403 4404 if (outValues) { 4405 /* get the point-to-point submatrix */ 4406 for (f = 0; f < numFields; f++) { 4407 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 4408 } 4409 } 4410 } 4411 else { 4412 newPoints[2 * newP] = b; 4413 newPoints[2 * newP + 1] = o; 4414 newP++; 4415 } 4416 } 4417 } else { 4418 for (p = 0; p < numPoints; p++) { 4419 PetscInt b = points[2*p]; 4420 PetscInt o = points[2*p+1]; 4421 PetscInt bDof = 0, bSecDof; 4422 4423 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 4424 if (!bSecDof) { 4425 continue; 4426 } 4427 if (b >= aStart && b < aEnd) { 4428 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4429 } 4430 if (bDof) { 4431 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 4432 4433 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4434 ierr = DMPlexGetIndicesPoint_Internal(cSec, b, bOff, &bEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4435 4436 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4437 for (q = 0; q < bDof; q++) { 4438 PetscInt a = anchors[bOff + q], aOff; 4439 4440 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4441 4442 newPoints[2*(newP + q)] = a; 4443 newPoints[2*(newP + q) + 1] = 0; 4444 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4445 ierr = DMPlexGetIndicesPoint_Internal(section, a, aOff, &bAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4446 } 4447 newP += bDof; 4448 4449 /* get the point-to-point submatrix */ 4450 if (outValues) { 4451 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 4452 } 4453 } 4454 else { 4455 newPoints[2 * newP] = b; 4456 newPoints[2 * newP + 1] = o; 4457 newP++; 4458 } 4459 } 4460 } 4461 4462 if (outValues) { 4463 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4464 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 4465 /* multiply constraints on the right */ 4466 if (numFields) { 4467 for (f = 0; f < numFields; f++) { 4468 PetscInt oldOff = offsets[f]; 4469 4470 for (p = 0; p < numPoints; p++) { 4471 PetscInt cStart = newPointOffsets[f][p]; 4472 PetscInt b = points[2 * p]; 4473 PetscInt c, r, k; 4474 PetscInt dof; 4475 4476 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4477 if (!dof) { 4478 continue; 4479 } 4480 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4481 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 4482 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 4483 4484 for (r = 0; r < numIndices; r++) { 4485 for (c = 0; c < nCols; c++) { 4486 for (k = 0; k < dof; k++) { 4487 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4488 } 4489 } 4490 } 4491 } 4492 else { 4493 /* copy this column as is */ 4494 for (r = 0; r < numIndices; r++) { 4495 for (c = 0; c < dof; c++) { 4496 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4497 } 4498 } 4499 } 4500 oldOff += dof; 4501 } 4502 } 4503 } 4504 else { 4505 PetscInt oldOff = 0; 4506 for (p = 0; p < numPoints; p++) { 4507 PetscInt cStart = newPointOffsets[0][p]; 4508 PetscInt b = points[2 * p]; 4509 PetscInt c, r, k; 4510 PetscInt dof; 4511 4512 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4513 if (!dof) { 4514 continue; 4515 } 4516 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4517 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 4518 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 4519 4520 for (r = 0; r < numIndices; r++) { 4521 for (c = 0; c < nCols; c++) { 4522 for (k = 0; k < dof; k++) { 4523 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4524 } 4525 } 4526 } 4527 } 4528 else { 4529 /* copy this column as is */ 4530 for (r = 0; r < numIndices; r++) { 4531 for (c = 0; c < dof; c++) { 4532 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4533 } 4534 } 4535 } 4536 oldOff += dof; 4537 } 4538 } 4539 4540 if (multiplyLeft) { 4541 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4542 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 4543 /* multiply constraints transpose on the left */ 4544 if (numFields) { 4545 for (f = 0; f < numFields; f++) { 4546 PetscInt oldOff = offsets[f]; 4547 4548 for (p = 0; p < numPoints; p++) { 4549 PetscInt rStart = newPointOffsets[f][p]; 4550 PetscInt b = points[2 * p]; 4551 PetscInt c, r, k; 4552 PetscInt dof; 4553 4554 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4555 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4556 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 4557 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 4558 4559 for (r = 0; r < nRows; r++) { 4560 for (c = 0; c < newNumIndices; c++) { 4561 for (k = 0; k < dof; k++) { 4562 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4563 } 4564 } 4565 } 4566 } 4567 else { 4568 /* copy this row as is */ 4569 for (r = 0; r < dof; r++) { 4570 for (c = 0; c < newNumIndices; c++) { 4571 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4572 } 4573 } 4574 } 4575 oldOff += dof; 4576 } 4577 } 4578 } 4579 else { 4580 PetscInt oldOff = 0; 4581 4582 for (p = 0; p < numPoints; p++) { 4583 PetscInt rStart = newPointOffsets[0][p]; 4584 PetscInt b = points[2 * p]; 4585 PetscInt c, r, k; 4586 PetscInt dof; 4587 4588 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4589 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4590 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 4591 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 4592 4593 for (r = 0; r < nRows; r++) { 4594 for (c = 0; c < newNumIndices; c++) { 4595 for (k = 0; k < dof; k++) { 4596 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4597 } 4598 } 4599 } 4600 } 4601 else { 4602 /* copy this row as is */ 4603 for (r = 0; r < dof; r++) { 4604 for (c = 0; c < newNumIndices; c++) { 4605 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4606 } 4607 } 4608 } 4609 oldOff += dof; 4610 } 4611 } 4612 4613 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4614 } 4615 else { 4616 newValues = tmpValues; 4617 } 4618 } 4619 4620 /* clean up */ 4621 ierr = DMRestoreWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4622 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4623 4624 if (numFields) { 4625 for (f = 0; f < numFields; f++) { 4626 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4627 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4628 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4629 } 4630 } 4631 else { 4632 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4633 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4634 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4635 } 4636 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4637 4638 /* output */ 4639 if (outPoints) { 4640 *outPoints = newPoints; 4641 } 4642 else { 4643 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4644 } 4645 if (outValues) { 4646 *outValues = newValues; 4647 } 4648 else { 4649 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4650 } 4651 for (f = 0; f <= numFields; f++) { 4652 offsets[f] = newOffsets[f]; 4653 } 4654 PetscFunctionReturn(0); 4655 } 4656 4657 #undef __FUNCT__ 4658 #define __FUNCT__ "DMPlexGetClosureIndices" 4659 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 4660 { 4661 PetscSection clSection; 4662 IS clPoints; 4663 const PetscInt *clp; 4664 PetscInt *points = NULL, *pointsNew; 4665 PetscInt numPoints, numPointsNew; 4666 PetscInt offsets[32]; 4667 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 4668 PetscErrorCode ierr; 4669 4670 PetscFunctionBegin; 4671 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4672 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4673 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4674 if (numIndices) PetscValidPointer(numIndices, 4); 4675 PetscValidPointer(indices, 5); 4676 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4677 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 4678 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4679 /* Get points in closure */ 4680 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4681 if (!clPoints) { 4682 PetscInt pStart, pEnd, q; 4683 4684 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4685 /* Compress out points not in the section */ 4686 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4687 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4688 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4689 points[q*2] = points[p]; 4690 points[q*2+1] = points[p+1]; 4691 ++q; 4692 } 4693 } 4694 numPoints = q; 4695 } else { 4696 PetscInt dof, off; 4697 4698 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4699 numPoints = dof/2; 4700 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4701 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4702 points = (PetscInt *) &clp[off]; 4703 } 4704 /* Get number of indices and indices per field */ 4705 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 4706 PetscInt dof, fdof; 4707 4708 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4709 for (f = 0; f < Nf; ++f) { 4710 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4711 offsets[f+1] += fdof; 4712 } 4713 Nind += dof; 4714 } 4715 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 4716 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[Nf], Nind); 4717 /* Correct for hanging node constraints */ 4718 { 4719 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 4720 if (numPointsNew) { 4721 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4722 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4723 numPoints = numPointsNew; 4724 Nind = NindNew; 4725 points = pointsNew; 4726 } 4727 } 4728 /* Calculate indices */ 4729 ierr = DMGetWorkArray(dm, Nind, PETSC_INT, indices);CHKERRQ(ierr); 4730 if (Nf) { 4731 if (outOffsets) { 4732 PetscInt f; 4733 4734 for (f = 0; f <= Nf; f++) { 4735 outOffsets[f] = offsets[f]; 4736 } 4737 } 4738 for (p = 0; p < numPoints*2; p += 2) { 4739 PetscInt o = points[p+1]; 4740 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4741 DMPlexGetIndicesPointFields_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, *indices); 4742 } 4743 } else { 4744 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4745 PetscInt o = points[p+1]; 4746 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4747 DMPlexGetIndicesPoint_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, *indices); 4748 } 4749 } 4750 /* Cleanup points */ 4751 if (numPointsNew) { 4752 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, PETSC_INT, &pointsNew);CHKERRQ(ierr); 4753 } else { 4754 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4755 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4756 } 4757 if (numIndices) *numIndices = Nind; 4758 PetscFunctionReturn(0); 4759 } 4760 4761 #undef __FUNCT__ 4762 #define __FUNCT__ "DMPlexRestoreClosureIndices" 4763 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 4764 { 4765 PetscErrorCode ierr; 4766 4767 PetscFunctionBegin; 4768 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4769 PetscValidPointer(indices, 5); 4770 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, indices);CHKERRQ(ierr); 4771 PetscFunctionReturn(0); 4772 } 4773 4774 #undef __FUNCT__ 4775 #define __FUNCT__ "DMPlexMatSetClosure" 4776 /*@C 4777 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 4778 4779 Not collective 4780 4781 Input Parameters: 4782 + dm - The DM 4783 . section - The section describing the layout in v, or NULL to use the default section 4784 . globalSection - The section describing the layout in v, or NULL to use the default global section 4785 . A - The matrix 4786 . point - The sieve point in the DM 4787 . values - The array of values 4788 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4789 4790 Fortran Notes: 4791 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4792 4793 Level: intermediate 4794 4795 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 4796 @*/ 4797 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4798 { 4799 DM_Plex *mesh = (DM_Plex*) dm->data; 4800 PetscSection clSection; 4801 IS clPoints; 4802 PetscInt *points = NULL, *newPoints; 4803 const PetscInt *clp; 4804 PetscInt *indices; 4805 PetscInt offsets[32]; 4806 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 4807 PetscScalar *newValues; 4808 PetscErrorCode ierr; 4809 4810 PetscFunctionBegin; 4811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4812 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4813 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4814 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 4815 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4816 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 4817 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4818 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4819 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4820 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4821 if (!clPoints) { 4822 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4823 /* Compress out points not in the section */ 4824 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4825 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4826 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4827 points[q*2] = points[p]; 4828 points[q*2+1] = points[p+1]; 4829 ++q; 4830 } 4831 } 4832 numPoints = q; 4833 } else { 4834 PetscInt dof, off; 4835 4836 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4837 numPoints = dof/2; 4838 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4839 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4840 points = (PetscInt *) &clp[off]; 4841 } 4842 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 4843 PetscInt fdof; 4844 4845 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4846 for (f = 0; f < numFields; ++f) { 4847 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4848 offsets[f+1] += fdof; 4849 } 4850 numIndices += dof; 4851 } 4852 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 4853 4854 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 4855 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 4856 if (newNumPoints) { 4857 if (!clPoints) { 4858 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4859 } else { 4860 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4861 } 4862 numPoints = newNumPoints; 4863 numIndices = newNumIndices; 4864 points = newPoints; 4865 values = newValues; 4866 } 4867 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4868 if (numFields) { 4869 for (p = 0; p < numPoints*2; p += 2) { 4870 PetscInt o = points[p+1]; 4871 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4872 DMPlexGetIndicesPointFields_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 4873 } 4874 } else { 4875 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4876 PetscInt o = points[p+1]; 4877 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4878 DMPlexGetIndicesPoint_Internal(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 4879 } 4880 } 4881 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 4882 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 4883 if (mesh->printFEM > 1) { 4884 PetscInt i; 4885 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 4886 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %d", indices[i]);CHKERRQ(ierr);} 4887 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 4888 } 4889 if (ierr) { 4890 PetscMPIInt rank; 4891 PetscErrorCode ierr2; 4892 4893 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4894 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4895 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 4896 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 4897 CHKERRQ(ierr); 4898 } 4899 if (newNumPoints) { 4900 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4901 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4902 } 4903 else { 4904 if (!clPoints) { 4905 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4906 } else { 4907 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4908 } 4909 } 4910 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4911 PetscFunctionReturn(0); 4912 } 4913 4914 #undef __FUNCT__ 4915 #define __FUNCT__ "DMPlexMatSetClosureRefined" 4916 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4917 { 4918 DM_Plex *mesh = (DM_Plex*) dmf->data; 4919 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4920 PetscInt *cpoints = NULL; 4921 PetscInt *findices, *cindices; 4922 PetscInt foffsets[32], coffsets[32]; 4923 CellRefiner cellRefiner; 4924 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4925 PetscErrorCode ierr; 4926 4927 PetscFunctionBegin; 4928 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4929 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4930 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4931 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4932 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4933 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4934 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4935 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4936 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4937 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4938 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 4939 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4940 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4941 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4942 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4943 /* Column indices */ 4944 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4945 maxFPoints = numCPoints; 4946 /* Compress out points not in the section */ 4947 /* TODO: Squeeze out points with 0 dof as well */ 4948 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4949 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4950 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4951 cpoints[q*2] = cpoints[p]; 4952 cpoints[q*2+1] = cpoints[p+1]; 4953 ++q; 4954 } 4955 } 4956 numCPoints = q; 4957 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4958 PetscInt fdof; 4959 4960 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4961 if (!dof) continue; 4962 for (f = 0; f < numFields; ++f) { 4963 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4964 coffsets[f+1] += fdof; 4965 } 4966 numCIndices += dof; 4967 } 4968 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4969 /* Row indices */ 4970 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4971 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4972 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4973 for (r = 0, q = 0; r < numSubcells; ++r) { 4974 /* TODO Map from coarse to fine cells */ 4975 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4976 /* Compress out points not in the section */ 4977 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4978 for (p = 0; p < numFPoints*2; p += 2) { 4979 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4980 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4981 if (!dof) continue; 4982 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4983 if (s < q) continue; 4984 ftotpoints[q*2] = fpoints[p]; 4985 ftotpoints[q*2+1] = fpoints[p+1]; 4986 ++q; 4987 } 4988 } 4989 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4990 } 4991 numFPoints = q; 4992 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 4993 PetscInt fdof; 4994 4995 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 4996 if (!dof) continue; 4997 for (f = 0; f < numFields; ++f) { 4998 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 4999 foffsets[f+1] += fdof; 5000 } 5001 numFIndices += dof; 5002 } 5003 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5004 5005 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5006 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5007 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5008 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5009 if (numFields) { 5010 for (p = 0; p < numFPoints*2; p += 2) { 5011 PetscInt o = ftotpoints[p+1]; 5012 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5013 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5014 } 5015 for (p = 0; p < numCPoints*2; p += 2) { 5016 PetscInt o = cpoints[p+1]; 5017 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5018 DMPlexGetIndicesPointFields_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5019 } 5020 } else { 5021 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5022 PetscInt o = ftotpoints[p+1]; 5023 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5024 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5025 } 5026 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5027 PetscInt o = cpoints[p+1]; 5028 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5029 DMPlexGetIndicesPoint_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5030 } 5031 } 5032 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5033 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5034 if (ierr) { 5035 PetscMPIInt rank; 5036 PetscErrorCode ierr2; 5037 5038 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5039 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5040 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5041 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 5042 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 5043 CHKERRQ(ierr); 5044 } 5045 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5046 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5047 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5048 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5049 PetscFunctionReturn(0); 5050 } 5051 5052 #undef __FUNCT__ 5053 #define __FUNCT__ "DMPlexMatGetClosureIndicesRefined" 5054 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5055 { 5056 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5057 PetscInt *cpoints = NULL; 5058 PetscInt foffsets[32], coffsets[32]; 5059 CellRefiner cellRefiner; 5060 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5061 PetscErrorCode ierr; 5062 5063 PetscFunctionBegin; 5064 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5065 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5066 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5067 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5068 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5069 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5070 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5071 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5072 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5073 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5074 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5075 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5076 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5077 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5078 /* Column indices */ 5079 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5080 maxFPoints = numCPoints; 5081 /* Compress out points not in the section */ 5082 /* TODO: Squeeze out points with 0 dof as well */ 5083 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5084 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5085 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5086 cpoints[q*2] = cpoints[p]; 5087 cpoints[q*2+1] = cpoints[p+1]; 5088 ++q; 5089 } 5090 } 5091 numCPoints = q; 5092 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5093 PetscInt fdof; 5094 5095 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5096 if (!dof) continue; 5097 for (f = 0; f < numFields; ++f) { 5098 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5099 coffsets[f+1] += fdof; 5100 } 5101 numCIndices += dof; 5102 } 5103 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5104 /* Row indices */ 5105 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5106 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5107 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5108 for (r = 0, q = 0; r < numSubcells; ++r) { 5109 /* TODO Map from coarse to fine cells */ 5110 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5111 /* Compress out points not in the section */ 5112 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5113 for (p = 0; p < numFPoints*2; p += 2) { 5114 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5115 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5116 if (!dof) continue; 5117 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5118 if (s < q) continue; 5119 ftotpoints[q*2] = fpoints[p]; 5120 ftotpoints[q*2+1] = fpoints[p+1]; 5121 ++q; 5122 } 5123 } 5124 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5125 } 5126 numFPoints = q; 5127 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5128 PetscInt fdof; 5129 5130 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5131 if (!dof) continue; 5132 for (f = 0; f < numFields; ++f) { 5133 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5134 foffsets[f+1] += fdof; 5135 } 5136 numFIndices += dof; 5137 } 5138 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5139 5140 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5141 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5142 if (numFields) { 5143 for (p = 0; p < numFPoints*2; p += 2) { 5144 PetscInt o = ftotpoints[p+1]; 5145 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5146 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5147 } 5148 for (p = 0; p < numCPoints*2; p += 2) { 5149 PetscInt o = cpoints[p+1]; 5150 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5151 DMPlexGetIndicesPointFields_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5152 } 5153 } else { 5154 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5155 PetscInt o = ftotpoints[p+1]; 5156 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5157 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5158 } 5159 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5160 PetscInt o = cpoints[p+1]; 5161 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5162 DMPlexGetIndicesPoint_Internal(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5163 } 5164 } 5165 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5166 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5167 PetscFunctionReturn(0); 5168 } 5169 5170 #undef __FUNCT__ 5171 #define __FUNCT__ "DMPlexGetHybridBounds" 5172 /*@ 5173 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5174 5175 Input Parameter: 5176 . dm - The DMPlex object 5177 5178 Output Parameters: 5179 + cMax - The first hybrid cell 5180 . fMax - The first hybrid face 5181 . eMax - The first hybrid edge 5182 - vMax - The first hybrid vertex 5183 5184 Level: developer 5185 5186 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 5187 @*/ 5188 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5189 { 5190 DM_Plex *mesh = (DM_Plex*) dm->data; 5191 PetscInt dim; 5192 PetscErrorCode ierr; 5193 5194 PetscFunctionBegin; 5195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5196 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5197 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5198 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5199 if (eMax) *eMax = mesh->hybridPointMax[1]; 5200 if (vMax) *vMax = mesh->hybridPointMax[0]; 5201 PetscFunctionReturn(0); 5202 } 5203 5204 #undef __FUNCT__ 5205 #define __FUNCT__ "DMPlexSetHybridBounds" 5206 /*@ 5207 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 5208 5209 Input Parameters: 5210 . dm - The DMPlex object 5211 . cMax - The first hybrid cell 5212 . fMax - The first hybrid face 5213 . eMax - The first hybrid edge 5214 - vMax - The first hybrid vertex 5215 5216 Level: developer 5217 5218 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 5219 @*/ 5220 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 5221 { 5222 DM_Plex *mesh = (DM_Plex*) dm->data; 5223 PetscInt dim; 5224 PetscErrorCode ierr; 5225 5226 PetscFunctionBegin; 5227 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5228 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5229 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 5230 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 5231 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 5232 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 5233 PetscFunctionReturn(0); 5234 } 5235 5236 #undef __FUNCT__ 5237 #define __FUNCT__ "DMPlexGetVTKCellHeight" 5238 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 5239 { 5240 DM_Plex *mesh = (DM_Plex*) dm->data; 5241 5242 PetscFunctionBegin; 5243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5244 PetscValidPointer(cellHeight, 2); 5245 *cellHeight = mesh->vtkCellHeight; 5246 PetscFunctionReturn(0); 5247 } 5248 5249 #undef __FUNCT__ 5250 #define __FUNCT__ "DMPlexSetVTKCellHeight" 5251 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 5252 { 5253 DM_Plex *mesh = (DM_Plex*) dm->data; 5254 5255 PetscFunctionBegin; 5256 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5257 mesh->vtkCellHeight = cellHeight; 5258 PetscFunctionReturn(0); 5259 } 5260 5261 #undef __FUNCT__ 5262 #define __FUNCT__ "DMPlexCreateNumbering_Private" 5263 /* We can easily have a form that takes an IS instead */ 5264 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 5265 { 5266 PetscSection section, globalSection; 5267 PetscInt *numbers, p; 5268 PetscErrorCode ierr; 5269 5270 PetscFunctionBegin; 5271 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5272 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 5273 for (p = pStart; p < pEnd; ++p) { 5274 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 5275 } 5276 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 5277 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 5278 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 5279 for (p = pStart; p < pEnd; ++p) { 5280 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 5281 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 5282 else numbers[p-pStart] += shift; 5283 } 5284 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 5285 if (globalSize) { 5286 PetscLayout layout; 5287 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 5288 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 5289 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 5290 } 5291 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5292 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 5293 PetscFunctionReturn(0); 5294 } 5295 5296 #undef __FUNCT__ 5297 #define __FUNCT__ "DMPlexCreateCellNumbering_Internal" 5298 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 5299 { 5300 PetscInt cellHeight, cStart, cEnd, cMax; 5301 PetscErrorCode ierr; 5302 5303 PetscFunctionBegin; 5304 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 5305 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5306 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5307 if (cMax >= 0 && !includeHybrid) cEnd = PetscMin(cEnd, cMax); 5308 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 5309 PetscFunctionReturn(0); 5310 } 5311 5312 #undef __FUNCT__ 5313 #define __FUNCT__ "DMPlexGetCellNumbering" 5314 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 5315 { 5316 DM_Plex *mesh = (DM_Plex*) dm->data; 5317 PetscErrorCode ierr; 5318 5319 PetscFunctionBegin; 5320 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5321 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 5322 *globalCellNumbers = mesh->globalCellNumbers; 5323 PetscFunctionReturn(0); 5324 } 5325 5326 #undef __FUNCT__ 5327 #define __FUNCT__ "DMPlexCreateVertexNumbering_Internal" 5328 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 5329 { 5330 PetscInt vStart, vEnd, vMax; 5331 PetscErrorCode ierr; 5332 5333 PetscFunctionBegin; 5334 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5335 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5336 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 5337 if (vMax >= 0 && !includeHybrid) vEnd = PetscMin(vEnd, vMax); 5338 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 5339 PetscFunctionReturn(0); 5340 } 5341 5342 #undef __FUNCT__ 5343 #define __FUNCT__ "DMPlexGetVertexNumbering" 5344 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 5345 { 5346 DM_Plex *mesh = (DM_Plex*) dm->data; 5347 PetscErrorCode ierr; 5348 5349 PetscFunctionBegin; 5350 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5351 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 5352 *globalVertexNumbers = mesh->globalVertexNumbers; 5353 PetscFunctionReturn(0); 5354 } 5355 5356 #undef __FUNCT__ 5357 #define __FUNCT__ "DMPlexCreatePointNumbering" 5358 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 5359 { 5360 IS nums[4]; 5361 PetscInt depths[4]; 5362 PetscInt depth, d, shift = 0; 5363 PetscErrorCode ierr; 5364 5365 PetscFunctionBegin; 5366 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5367 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5368 /* For unstratified meshes use dim instead of depth */ 5369 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 5370 depths[0] = depth; depths[1] = 0; 5371 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 5372 for (d = 0; d <= depth; ++d) { 5373 PetscInt pStart, pEnd, gsize; 5374 5375 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 5376 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 5377 shift += gsize; 5378 } 5379 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 5380 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 5381 PetscFunctionReturn(0); 5382 } 5383 5384 #undef __FUNCT__ 5385 #define __FUNCT__ "DMPlexCheckSymmetry" 5386 /*@ 5387 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5388 5389 Input Parameters: 5390 + dm - The DMPlex object 5391 5392 Note: This is a useful diagnostic when creating meshes programmatically. 5393 5394 Level: developer 5395 5396 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5397 @*/ 5398 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5399 { 5400 PetscSection coneSection, supportSection; 5401 const PetscInt *cone, *support; 5402 PetscInt coneSize, c, supportSize, s; 5403 PetscInt pStart, pEnd, p, csize, ssize; 5404 PetscErrorCode ierr; 5405 5406 PetscFunctionBegin; 5407 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5408 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5409 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5410 /* Check that point p is found in the support of its cone points, and vice versa */ 5411 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5412 for (p = pStart; p < pEnd; ++p) { 5413 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5414 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5415 for (c = 0; c < coneSize; ++c) { 5416 PetscBool dup = PETSC_FALSE; 5417 PetscInt d; 5418 for (d = c-1; d >= 0; --d) { 5419 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5420 } 5421 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5422 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5423 for (s = 0; s < supportSize; ++s) { 5424 if (support[s] == p) break; 5425 } 5426 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5427 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p);CHKERRQ(ierr); 5428 for (s = 0; s < coneSize; ++s) { 5429 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]);CHKERRQ(ierr); 5430 } 5431 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5432 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]);CHKERRQ(ierr); 5433 for (s = 0; s < supportSize; ++s) { 5434 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]);CHKERRQ(ierr); 5435 } 5436 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5437 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5438 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5439 } 5440 } 5441 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5442 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5443 for (s = 0; s < supportSize; ++s) { 5444 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5445 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5446 for (c = 0; c < coneSize; ++c) { 5447 if (cone[c] == p) break; 5448 } 5449 if (c >= coneSize) { 5450 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p);CHKERRQ(ierr); 5451 for (c = 0; c < supportSize; ++c) { 5452 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]);CHKERRQ(ierr); 5453 } 5454 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5455 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]);CHKERRQ(ierr); 5456 for (c = 0; c < coneSize; ++c) { 5457 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]);CHKERRQ(ierr); 5458 } 5459 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5460 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5461 } 5462 } 5463 } 5464 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5465 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5466 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5467 PetscFunctionReturn(0); 5468 } 5469 5470 #undef __FUNCT__ 5471 #define __FUNCT__ "DMPlexCheckSkeleton" 5472 /*@ 5473 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5474 5475 Input Parameters: 5476 + dm - The DMPlex object 5477 . isSimplex - Are the cells simplices or tensor products 5478 - cellHeight - Normally 0 5479 5480 Note: This is a useful diagnostic when creating meshes programmatically. 5481 5482 Level: developer 5483 5484 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5485 @*/ 5486 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5487 { 5488 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5489 PetscErrorCode ierr; 5490 5491 PetscFunctionBegin; 5492 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5493 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5494 switch (dim) { 5495 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5496 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5497 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5498 default: 5499 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5500 } 5501 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5502 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5503 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5504 cMax = cMax >= 0 ? cMax : cEnd; 5505 for (c = cStart; c < cMax; ++c) { 5506 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5507 5508 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5509 for (cl = 0; cl < closureSize*2; cl += 2) { 5510 const PetscInt p = closure[cl]; 5511 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5512 } 5513 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5514 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5515 } 5516 for (c = cMax; c < cEnd; ++c) { 5517 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5518 5519 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5520 for (cl = 0; cl < closureSize*2; cl += 2) { 5521 const PetscInt p = closure[cl]; 5522 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5523 } 5524 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5525 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5526 } 5527 PetscFunctionReturn(0); 5528 } 5529 5530 #undef __FUNCT__ 5531 #define __FUNCT__ "DMPlexCheckFaces" 5532 /*@ 5533 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5534 5535 Input Parameters: 5536 + dm - The DMPlex object 5537 . isSimplex - Are the cells simplices or tensor products 5538 - cellHeight - Normally 0 5539 5540 Note: This is a useful diagnostic when creating meshes programmatically. 5541 5542 Level: developer 5543 5544 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5545 @*/ 5546 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5547 { 5548 PetscInt pMax[4]; 5549 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5550 PetscErrorCode ierr; 5551 5552 PetscFunctionBegin; 5553 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5554 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5555 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5556 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5557 for (h = cellHeight; h < dim; ++h) { 5558 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5559 for (c = cStart; c < cEnd; ++c) { 5560 const PetscInt *cone, *ornt, *faces; 5561 PetscInt numFaces, faceSize, coneSize,f; 5562 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5563 5564 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5565 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5566 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5567 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5568 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5569 for (cl = 0; cl < closureSize*2; cl += 2) { 5570 const PetscInt p = closure[cl]; 5571 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5572 } 5573 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5574 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5575 for (f = 0; f < numFaces; ++f) { 5576 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5577 5578 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5579 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5580 const PetscInt p = fclosure[cl]; 5581 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5582 } 5583 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); 5584 for (v = 0; v < fnumCorners; ++v) { 5585 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]); 5586 } 5587 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5588 } 5589 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5590 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5591 } 5592 } 5593 PetscFunctionReturn(0); 5594 } 5595 5596 #undef __FUNCT__ 5597 #define __FUNCT__ "DMCreateInterpolation_Plex" 5598 /* Pointwise interpolation 5599 Just code FEM for now 5600 u^f = I u^c 5601 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5602 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5603 I_{ij} = psi^f_i phi^c_j 5604 */ 5605 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5606 { 5607 PetscSection gsc, gsf; 5608 PetscInt m, n; 5609 void *ctx; 5610 DM cdm; 5611 PetscBool regular; 5612 PetscErrorCode ierr; 5613 5614 PetscFunctionBegin; 5615 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5616 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5617 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5618 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5619 5620 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5621 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5622 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5623 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5624 5625 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 5626 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 5627 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5628 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5629 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 5630 /* Use naive scaling */ 5631 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5632 PetscFunctionReturn(0); 5633 } 5634 5635 #undef __FUNCT__ 5636 #define __FUNCT__ "DMCreateInjection_Plex" 5637 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 5638 { 5639 PetscErrorCode ierr; 5640 VecScatter ctx; 5641 5642 PetscFunctionBegin; 5643 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 5644 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 5645 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 5646 PetscFunctionReturn(0); 5647 } 5648 5649 #undef __FUNCT__ 5650 #define __FUNCT__ "DMCreateDefaultSection_Plex" 5651 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 5652 { 5653 PetscSection section; 5654 IS *bcPoints, *bcComps; 5655 PetscBool *isFE; 5656 PetscInt *bcFields, *numComp, *numDof; 5657 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 5658 PetscInt cStart, cEnd, cEndInterior; 5659 PetscErrorCode ierr; 5660 5661 PetscFunctionBegin; 5662 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 5663 if (!numFields) PetscFunctionReturn(0); 5664 /* FE and FV boundary conditions are handled slightly differently */ 5665 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 5666 for (f = 0; f < numFields; ++f) { 5667 PetscObject obj; 5668 PetscClassId id; 5669 5670 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5671 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 5672 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 5673 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 5674 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 5675 } 5676 /* Allocate boundary point storage for FEM boundaries */ 5677 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5678 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5679 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5680 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 5681 ierr = DMGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 5682 for (bd = 0; bd < numBd; ++bd) { 5683 PetscInt field; 5684 PetscBool isEssential; 5685 5686 ierr = DMGetBoundary(dm, bd, &isEssential, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5687 if (isFE[field] && isEssential) ++numBC; 5688 } 5689 /* Add ghost cell boundaries for FVM */ 5690 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 5691 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 5692 /* Constrain ghost cells for FV */ 5693 for (f = 0; f < numFields; ++f) { 5694 PetscInt *newidx, c; 5695 5696 if (isFE[f] || cEndInterior < 0) continue; 5697 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 5698 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 5699 bcFields[bc] = f; 5700 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5701 } 5702 /* Handle FEM Dirichlet boundaries */ 5703 for (bd = 0; bd < numBd; ++bd) { 5704 const char *bdLabel; 5705 DMLabel label; 5706 const PetscInt *comps; 5707 const PetscInt *values; 5708 PetscInt bd2, field, numComps, numValues; 5709 PetscBool isEssential, duplicate = PETSC_FALSE; 5710 5711 ierr = DMGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 5712 if (!isFE[field]) continue; 5713 ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 5714 /* Only want to modify label once */ 5715 for (bd2 = 0; bd2 < bd; ++bd2) { 5716 const char *bdname; 5717 ierr = DMGetBoundary(dm, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5718 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 5719 if (duplicate) break; 5720 } 5721 if (!duplicate && (isFE[field])) { 5722 /* don't complete cells, which are just present to give orientation to the boundary */ 5723 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 5724 } 5725 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 5726 if (isEssential) { 5727 PetscInt *newidx; 5728 PetscInt n, newn = 0, p, v; 5729 5730 bcFields[bc] = field; 5731 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 5732 for (v = 0; v < numValues; ++v) { 5733 IS tmp; 5734 const PetscInt *idx; 5735 5736 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5737 if (!tmp) continue; 5738 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5739 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5740 if (isFE[field]) { 5741 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 5742 } else { 5743 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 5744 } 5745 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5746 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5747 } 5748 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 5749 newn = 0; 5750 for (v = 0; v < numValues; ++v) { 5751 IS tmp; 5752 const PetscInt *idx; 5753 5754 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5755 if (!tmp) continue; 5756 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5757 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5758 if (isFE[field]) { 5759 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 5760 } else { 5761 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 5762 } 5763 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5764 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5765 } 5766 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5767 } 5768 } 5769 /* Handle discretization */ 5770 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 5771 for (f = 0; f < numFields; ++f) { 5772 PetscObject obj; 5773 5774 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5775 if (isFE[f]) { 5776 PetscFE fe = (PetscFE) obj; 5777 const PetscInt *numFieldDof; 5778 PetscInt d; 5779 5780 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 5781 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 5782 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 5783 } else { 5784 PetscFV fv = (PetscFV) obj; 5785 5786 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 5787 numDof[f*(dim+1)+dim] = numComp[f]; 5788 } 5789 } 5790 for (f = 0; f < numFields; ++f) { 5791 PetscInt d; 5792 for (d = 1; d < dim; ++d) { 5793 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."); 5794 } 5795 } 5796 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 5797 for (f = 0; f < numFields; ++f) { 5798 PetscFE fe; 5799 const char *name; 5800 5801 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 5802 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 5803 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 5804 } 5805 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 5806 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5807 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 5808 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 5809 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 5810 ierr = PetscFree(isFE);CHKERRQ(ierr); 5811 PetscFunctionReturn(0); 5812 } 5813 5814 #undef __FUNCT__ 5815 #define __FUNCT__ "DMPlexGetRegularRefinement" 5816 /*@ 5817 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 5818 5819 Input Parameter: 5820 . dm - The DMPlex object 5821 5822 Output Parameter: 5823 . regular - The flag 5824 5825 Level: intermediate 5826 5827 .seealso: DMPlexSetRegularRefinement() 5828 @*/ 5829 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 5830 { 5831 PetscFunctionBegin; 5832 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5833 PetscValidPointer(regular, 2); 5834 *regular = ((DM_Plex *) dm->data)->regularRefinement; 5835 PetscFunctionReturn(0); 5836 } 5837 5838 #undef __FUNCT__ 5839 #define __FUNCT__ "DMPlexSetRegularRefinement" 5840 /*@ 5841 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 5842 5843 Input Parameters: 5844 + dm - The DMPlex object 5845 - regular - The flag 5846 5847 Level: intermediate 5848 5849 .seealso: DMPlexGetRegularRefinement() 5850 @*/ 5851 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 5852 { 5853 PetscFunctionBegin; 5854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5855 ((DM_Plex *) dm->data)->regularRefinement = regular; 5856 PetscFunctionReturn(0); 5857 } 5858 5859 /* anchors */ 5860 #undef __FUNCT__ 5861 #define __FUNCT__ "DMPlexGetAnchors" 5862 /*@ 5863 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 5864 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 5865 5866 not collective 5867 5868 Input Parameters: 5869 . dm - The DMPlex object 5870 5871 Output Parameters: 5872 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 5873 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 5874 5875 5876 Level: intermediate 5877 5878 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 5879 @*/ 5880 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 5881 { 5882 DM_Plex *plex = (DM_Plex *)dm->data; 5883 PetscErrorCode ierr; 5884 5885 PetscFunctionBegin; 5886 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5887 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 5888 if (anchorSection) *anchorSection = plex->anchorSection; 5889 if (anchorIS) *anchorIS = plex->anchorIS; 5890 PetscFunctionReturn(0); 5891 } 5892 5893 #undef __FUNCT__ 5894 #define __FUNCT__ "DMPlexSetAnchors" 5895 /*@ 5896 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 5897 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 5898 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 5899 5900 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 5901 DMGetConstraints() and filling in the entries in the constraint matrix. 5902 5903 collective on dm 5904 5905 Input Parameters: 5906 + dm - The DMPlex object 5907 . 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). 5908 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 5909 5910 The reference counts of anchorSection and anchorIS are incremented. 5911 5912 Level: intermediate 5913 5914 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 5915 @*/ 5916 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 5917 { 5918 DM_Plex *plex = (DM_Plex *)dm->data; 5919 PetscMPIInt result; 5920 PetscErrorCode ierr; 5921 5922 PetscFunctionBegin; 5923 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5924 if (anchorSection) { 5925 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 5926 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 5927 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 5928 } 5929 if (anchorIS) { 5930 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 5931 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 5932 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 5933 } 5934 5935 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 5936 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 5937 plex->anchorSection = anchorSection; 5938 5939 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 5940 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 5941 plex->anchorIS = anchorIS; 5942 5943 #if defined(PETSC_USE_DEBUG) 5944 if (anchorIS && anchorSection) { 5945 PetscInt size, a, pStart, pEnd; 5946 const PetscInt *anchors; 5947 5948 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 5949 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 5950 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 5951 for (a = 0; a < size; a++) { 5952 PetscInt p; 5953 5954 p = anchors[a]; 5955 if (p >= pStart && p < pEnd) { 5956 PetscInt dof; 5957 5958 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 5959 if (dof) { 5960 PetscErrorCode ierr2; 5961 5962 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 5963 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %d cannot be constrained and an anchor",p); 5964 } 5965 } 5966 } 5967 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 5968 } 5969 #endif 5970 /* reset the generic constraints */ 5971 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 5972 PetscFunctionReturn(0); 5973 } 5974 5975 #undef __FUNCT__ 5976 #define __FUNCT__ "DMPlexCreateConstraintSection_Anchors" 5977 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 5978 { 5979 PetscSection anchorSection; 5980 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 5981 PetscErrorCode ierr; 5982 5983 PetscFunctionBegin; 5984 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5985 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 5986 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 5987 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 5988 if (numFields) { 5989 PetscInt f; 5990 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 5991 5992 for (f = 0; f < numFields; f++) { 5993 PetscInt numComp; 5994 5995 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 5996 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 5997 } 5998 } 5999 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6000 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 6001 pStart = PetscMax(pStart,sStart); 6002 pEnd = PetscMin(pEnd,sEnd); 6003 pEnd = PetscMax(pStart,pEnd); 6004 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 6005 for (p = pStart; p < pEnd; p++) { 6006 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6007 if (dof) { 6008 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 6009 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 6010 for (f = 0; f < numFields; f++) { 6011 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 6012 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 6013 } 6014 } 6015 } 6016 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 6017 PetscFunctionReturn(0); 6018 } 6019 6020 #undef __FUNCT__ 6021 #define __FUNCT__ "DMPlexCreateConstraintMatrix_Anchors" 6022 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 6023 { 6024 PetscSection aSec; 6025 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 6026 const PetscInt *anchors; 6027 PetscInt numFields, f; 6028 IS aIS; 6029 PetscErrorCode ierr; 6030 6031 PetscFunctionBegin; 6032 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6033 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 6034 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 6035 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 6036 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 6037 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 6038 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6039 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6040 /* cSec will be a subset of aSec and section */ 6041 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 6042 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 6043 i[0] = 0; 6044 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6045 for (p = pStart; p < pEnd; p++) { 6046 PetscInt rDof, rOff, r; 6047 6048 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6049 if (!rDof) continue; 6050 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6051 if (numFields) { 6052 for (f = 0; f < numFields; f++) { 6053 annz = 0; 6054 for (r = 0; r < rDof; r++) { 6055 a = anchors[rOff + r]; 6056 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6057 annz += aDof; 6058 } 6059 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6060 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 6061 for (q = 0; q < dof; q++) { 6062 i[off + q + 1] = i[off + q] + annz; 6063 } 6064 } 6065 } 6066 else { 6067 annz = 0; 6068 for (q = 0; q < dof; q++) { 6069 a = anchors[off + q]; 6070 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6071 annz += aDof; 6072 } 6073 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6074 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 6075 for (q = 0; q < dof; q++) { 6076 i[off + q + 1] = i[off + q] + annz; 6077 } 6078 } 6079 } 6080 nnz = i[m]; 6081 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 6082 offset = 0; 6083 for (p = pStart; p < pEnd; p++) { 6084 if (numFields) { 6085 for (f = 0; f < numFields; f++) { 6086 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6087 for (q = 0; q < dof; q++) { 6088 PetscInt rDof, rOff, r; 6089 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6090 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6091 for (r = 0; r < rDof; r++) { 6092 PetscInt s; 6093 6094 a = anchors[rOff + r]; 6095 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6096 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 6097 for (s = 0; s < aDof; s++) { 6098 j[offset++] = aOff + s; 6099 } 6100 } 6101 } 6102 } 6103 } 6104 else { 6105 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6106 for (q = 0; q < dof; q++) { 6107 PetscInt rDof, rOff, r; 6108 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6109 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6110 for (r = 0; r < rDof; r++) { 6111 PetscInt s; 6112 6113 a = anchors[rOff + r]; 6114 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6115 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 6116 for (s = 0; s < aDof; s++) { 6117 j[offset++] = aOff + s; 6118 } 6119 } 6120 } 6121 } 6122 } 6123 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 6124 ierr = PetscFree(i);CHKERRQ(ierr); 6125 ierr = PetscFree(j);CHKERRQ(ierr); 6126 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 6127 PetscFunctionReturn(0); 6128 } 6129 6130 #undef __FUNCT__ 6131 #define __FUNCT__ "DMCreateDefaultConstraints_Plex" 6132 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 6133 { 6134 DM_Plex *plex = (DM_Plex *)dm->data; 6135 PetscSection anchorSection, section, cSec; 6136 Mat cMat; 6137 PetscErrorCode ierr; 6138 6139 PetscFunctionBegin; 6140 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6141 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6142 if (anchorSection) { 6143 PetscDS ds; 6144 PetscInt nf; 6145 6146 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 6147 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 6148 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 6149 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 6150 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 6151 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 6152 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 6153 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 6154 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 6155 } 6156 PetscFunctionReturn(0); 6157 } 6158