1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petsc/private/vecimpl.h> 4 #include <petsc/private/glvisvecimpl.h> 5 #include <petscsf.h> 6 #include <petscds.h> 7 #include <petscdraw.h> 8 #include <petscdmfield.h> 9 10 /* Logging support */ 11 PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF; 12 13 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 14 15 /*@ 16 DMPlexRefineSimplexToTensor - Uniformly refines simplicial cells into tensor product cells. 17 3 quadrilaterals per triangle in 2D and 4 hexahedra per tetrahedron in 3D. 18 19 Collective 20 21 Input Parameters: 22 . dm - The DMPlex object 23 24 Output Parameters: 25 . dmRefined - The refined DMPlex object 26 27 Note: Returns NULL if the mesh is already a tensor product mesh. 28 29 Level: intermediate 30 31 .seealso: DMPlexCreate(), DMPlexSetRefinementUniform() 32 @*/ 33 PetscErrorCode DMPlexRefineSimplexToTensor(DM dm, DM *dmRefined) 34 { 35 CellRefiner cellRefiner; 36 DMPolytopeType ct; 37 PetscInt dim, cMax, fMax, cStart, cEnd; 38 PetscBool lop, allnoop, localized; 39 PetscErrorCode ierr; 40 41 PetscFunctionBegin; 42 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43 PetscValidPointer(dmRefined, 1); 44 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 45 ierr = DMPlexGetHybridBounds(dm,&cMax,&fMax,NULL,NULL);CHKERRQ(ierr); 46 ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 47 if (!(cEnd - cStart)) cellRefiner = REFINER_NOOP; 48 else { 49 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 50 switch (ct) { 51 case DM_POLYTOPE_POINT: 52 case DM_POLYTOPE_SEGMENT: 53 cellRefiner = REFINER_NOOP;break; 54 case DM_POLYTOPE_TRIANGLE: 55 if (cMax >= 0) cellRefiner = REFINER_HYBRID_SIMPLEX_TO_HEX_2D; 56 else cellRefiner = REFINER_SIMPLEX_TO_HEX_2D; 57 break; 58 case DM_POLYTOPE_QUADRILATERAL: 59 if (cMax >= 0) cellRefiner = REFINER_HYBRID_SIMPLEX_TO_HEX_2D; 60 else cellRefiner = REFINER_NOOP; 61 break; 62 case DM_POLYTOPE_TETRAHEDRON: 63 if (cMax >= 0) cellRefiner = REFINER_HYBRID_SIMPLEX_TO_HEX_3D; 64 else cellRefiner = REFINER_SIMPLEX_TO_HEX_3D; 65 break; 66 case DM_POLYTOPE_TRI_PRISM_TENSOR: 67 cellRefiner = REFINER_HYBRID_SIMPLEX_TO_HEX_3D;break; 68 case DM_POLYTOPE_HEXAHEDRON: 69 if (cMax >= 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Simplex2Tensor in 3D with Hybrid mesh not yet done"); 70 else cellRefiner = REFINER_NOOP; 71 break; 72 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle cell polytope type %s", DMPolytopeTypes[ct]); 73 } 74 } 75 /* return if we don't need to refine */ 76 lop = (cellRefiner == REFINER_NOOP) ? PETSC_TRUE : PETSC_FALSE; 77 ierr = MPIU_Allreduce(&lop,&allnoop,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 78 if (allnoop) { 79 *dmRefined = NULL; 80 PetscFunctionReturn(0); 81 } 82 ierr = DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 83 ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr); 84 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 85 if (localized) { 86 ierr = DMLocalizeCoordinates(*dmRefined);CHKERRQ(ierr); 87 } 88 PetscFunctionReturn(0); 89 } 90 91 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 92 { 93 PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, cMax; 94 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 95 PetscErrorCode ierr; 96 97 PetscFunctionBegin; 98 *ft = PETSC_VTK_INVALID; 99 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 100 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 101 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 102 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 103 cEnd = cMax < 0 ? cEnd : cMax; 104 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 105 if (field >= 0) { 106 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 107 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 108 } else { 109 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 110 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 111 } 112 ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 113 if (globalvcdof[0]) { 114 *sStart = vStart; 115 *sEnd = vEnd; 116 if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 117 else *ft = PETSC_VTK_POINT_FIELD; 118 } else if (globalvcdof[1]) { 119 *sStart = cStart; 120 *sEnd = cEnd; 121 if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 122 else *ft = PETSC_VTK_CELL_FIELD; 123 } else { 124 if (field >= 0) { 125 const char *fieldname; 126 127 ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 128 ierr = PetscInfo2((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 129 } else { 130 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output typp of section\"%s\"\n");CHKERRQ(ierr); 131 } 132 } 133 PetscFunctionReturn(0); 134 } 135 136 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 137 { 138 DM dm; 139 PetscSection s; 140 PetscDraw draw, popup; 141 DM cdm; 142 PetscSection coordSection; 143 Vec coordinates; 144 const PetscScalar *coords, *array; 145 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 146 PetscReal vbound[2], time; 147 PetscBool isnull, flg; 148 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 149 const char *name; 150 char title[PETSC_MAX_PATH_LEN]; 151 PetscErrorCode ierr; 152 153 PetscFunctionBegin; 154 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 155 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 156 if (isnull) PetscFunctionReturn(0); 157 158 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 159 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 160 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 161 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 162 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 163 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 164 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 165 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 166 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 167 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 168 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 169 170 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 171 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 172 173 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 174 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 175 for (c = 0; c < N; c += dim) { 176 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 177 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 178 } 179 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 180 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 181 182 /* Could implement something like DMDASelectFields() */ 183 for (f = 0; f < Nf; ++f) { 184 DM fdm = dm; 185 Vec fv = v; 186 IS fis; 187 char prefix[PETSC_MAX_PATH_LEN]; 188 const char *fname; 189 190 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 191 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 192 193 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 194 else {prefix[0] = '\0';} 195 if (Nf > 1) { 196 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 197 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 198 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 199 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 200 } 201 for (comp = 0; comp < Nc; ++comp, ++w) { 202 PetscInt nmax = 2; 203 204 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 205 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 206 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 207 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 208 209 /* TODO Get max and min only for this component */ 210 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 211 if (!flg) { 212 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 213 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 214 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 215 } 216 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 217 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 218 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 219 220 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 221 for (c = cStart; c < cEnd; ++c) { 222 PetscScalar *coords = NULL, *a = NULL; 223 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 224 225 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 226 if (a) { 227 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 228 color[1] = color[2] = color[3] = color[0]; 229 } else { 230 PetscScalar *vals = NULL; 231 PetscInt numVals, va; 232 233 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 234 if (numVals % Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", Nc, numVals); 235 switch (numVals/Nc) { 236 case 3: /* P1 Triangle */ 237 case 4: /* P1 Quadrangle */ 238 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 239 break; 240 case 6: /* P2 Triangle */ 241 case 8: /* P2 Quadrangle */ 242 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 243 break; 244 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 245 } 246 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 247 } 248 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 249 switch (numCoords) { 250 case 6: 251 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 252 break; 253 case 8: 254 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 255 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]);CHKERRQ(ierr); 256 break; 257 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 258 } 259 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 260 } 261 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 262 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 263 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 264 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 265 } 266 if (Nf > 1) { 267 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 268 ierr = ISDestroy(&fis);CHKERRQ(ierr); 269 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 270 } 271 } 272 PetscFunctionReturn(0); 273 } 274 275 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 276 { 277 DM dm; 278 Vec locv; 279 const char *name; 280 PetscSection section; 281 PetscInt pStart, pEnd; 282 PetscInt numFields; 283 PetscViewerVTKFieldType ft; 284 PetscErrorCode ierr; 285 286 PetscFunctionBegin; 287 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 288 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 289 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 290 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 291 ierr = VecCopy(v, locv);CHKERRQ(ierr); 292 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 293 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 294 if (!numFields) { 295 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 296 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 297 } else { 298 PetscInt f; 299 300 for (f = 0; f < numFields; f++) { 301 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 302 if (ft == PETSC_VTK_INVALID) continue; 303 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 304 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 305 } 306 ierr = VecDestroy(&locv);CHKERRQ(ierr); 307 } 308 PetscFunctionReturn(0); 309 } 310 311 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 312 { 313 DM dm; 314 PetscBool isvtk, ishdf5, isdraw, isglvis; 315 PetscErrorCode ierr; 316 317 PetscFunctionBegin; 318 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 319 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 320 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 321 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 322 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 323 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 324 if (isvtk || ishdf5 || isdraw || isglvis) { 325 PetscInt i,numFields; 326 PetscObject fe; 327 PetscBool fem = PETSC_FALSE; 328 Vec locv = v; 329 const char *name; 330 PetscInt step; 331 PetscReal time; 332 333 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 334 for (i=0; i<numFields; i++) { 335 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 336 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 337 } 338 if (fem) { 339 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 340 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 341 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 342 ierr = VecCopy(v, locv);CHKERRQ(ierr); 343 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 344 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 345 } 346 if (isvtk) { 347 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 348 } else if (ishdf5) { 349 #if defined(PETSC_HAVE_HDF5) 350 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 351 #else 352 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 353 #endif 354 } else if (isdraw) { 355 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 356 } else if (isglvis) { 357 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 358 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 359 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 360 } 361 if (fem) {ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr);} 362 } else { 363 PetscBool isseq; 364 365 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 366 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 367 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 368 } 369 PetscFunctionReturn(0); 370 } 371 372 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 373 { 374 DM dm; 375 PetscBool isvtk, ishdf5, isdraw, isglvis; 376 PetscErrorCode ierr; 377 378 PetscFunctionBegin; 379 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 380 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 381 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 382 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 383 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 384 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 385 if (isvtk || isdraw || isglvis) { 386 Vec locv; 387 const char *name; 388 389 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 390 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 391 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 392 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 393 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 394 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 395 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 396 } else if (ishdf5) { 397 #if defined(PETSC_HAVE_HDF5) 398 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 399 #else 400 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 401 #endif 402 } else { 403 PetscBool isseq; 404 405 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 406 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 407 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 408 } 409 PetscFunctionReturn(0); 410 } 411 412 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 413 { 414 DM dm; 415 MPI_Comm comm; 416 PetscViewerFormat format; 417 Vec v; 418 PetscBool isvtk, ishdf5; 419 PetscErrorCode ierr; 420 421 PetscFunctionBegin; 422 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 423 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 424 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 425 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 426 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 427 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 428 if (format == PETSC_VIEWER_NATIVE) { 429 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 430 /* this need a better fix */ 431 if (dm->useNatural) { 432 if (dm->sfNatural) { 433 const char *vecname; 434 PetscInt n, nroots; 435 436 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 437 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 438 if (n == nroots) { 439 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 440 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 441 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 442 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 443 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 444 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 445 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 446 } else v = originalv; 447 } else v = originalv; 448 449 if (ishdf5) { 450 #if defined(PETSC_HAVE_HDF5) 451 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 452 #else 453 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 454 #endif 455 } else if (isvtk) { 456 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 457 } else { 458 PetscBool isseq; 459 460 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 461 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 462 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 463 } 464 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 465 PetscFunctionReturn(0); 466 } 467 468 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 469 { 470 DM dm; 471 PetscBool ishdf5; 472 PetscErrorCode ierr; 473 474 PetscFunctionBegin; 475 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 476 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 477 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 478 if (ishdf5) { 479 DM dmBC; 480 Vec gv; 481 const char *name; 482 483 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 484 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 485 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 486 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 487 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 488 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 489 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 490 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 491 } else { 492 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 493 } 494 PetscFunctionReturn(0); 495 } 496 497 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 498 { 499 DM dm; 500 PetscBool ishdf5; 501 PetscErrorCode ierr; 502 503 PetscFunctionBegin; 504 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 505 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 506 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 507 if (ishdf5) { 508 #if defined(PETSC_HAVE_HDF5) 509 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 510 #else 511 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 512 #endif 513 } else { 514 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 515 } 516 PetscFunctionReturn(0); 517 } 518 519 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 520 { 521 DM dm; 522 PetscViewerFormat format; 523 PetscBool ishdf5; 524 PetscErrorCode ierr; 525 526 PetscFunctionBegin; 527 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 528 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 529 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 530 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 531 if (format == PETSC_VIEWER_NATIVE) { 532 if (dm->useNatural) { 533 if (dm->sfNatural) { 534 if (ishdf5) { 535 #if defined(PETSC_HAVE_HDF5) 536 Vec v; 537 const char *vecname; 538 539 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 540 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 541 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 542 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 543 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 544 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 545 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 546 #else 547 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 548 #endif 549 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 550 } 551 } else { 552 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 553 } 554 } 555 PetscFunctionReturn(0); 556 } 557 558 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 559 { 560 PetscSection coordSection; 561 Vec coordinates; 562 DMLabel depthLabel, celltypeLabel; 563 const char *name[4]; 564 const PetscScalar *a; 565 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 566 PetscErrorCode ierr; 567 568 PetscFunctionBegin; 569 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 570 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 571 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 572 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 573 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 574 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 575 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 576 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 577 name[0] = "vertex"; 578 name[1] = "edge"; 579 name[dim-1] = "face"; 580 name[dim] = "cell"; 581 for (c = cStart; c < cEnd; ++c) { 582 PetscInt *closure = NULL; 583 PetscInt closureSize, cl, ct; 584 585 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 586 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 587 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 588 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 589 for (cl = 0; cl < closureSize*2; cl += 2) { 590 PetscInt point = closure[cl], depth, dof, off, d, p; 591 592 if ((point < pStart) || (point >= pEnd)) continue; 593 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 594 if (!dof) continue; 595 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 596 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 597 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 598 for (p = 0; p < dof/dim; ++p) { 599 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 600 for (d = 0; d < dim; ++d) { 601 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 602 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 603 } 604 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 605 } 606 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 607 } 608 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 609 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 610 } 611 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 612 PetscFunctionReturn(0); 613 } 614 615 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 616 { 617 DM_Plex *mesh = (DM_Plex*) dm->data; 618 DM cdm; 619 DMLabel markers; 620 PetscSection coordSection; 621 Vec coordinates; 622 PetscViewerFormat format; 623 PetscErrorCode ierr; 624 625 PetscFunctionBegin; 626 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 627 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 628 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 629 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 630 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 631 const char *name; 632 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 633 PetscInt pStart, pEnd, p; 634 PetscMPIInt rank, size; 635 636 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 637 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 638 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 639 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 640 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 641 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 642 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 643 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 644 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 645 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 646 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 647 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 648 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 649 for (p = pStart; p < pEnd; ++p) { 650 PetscInt dof, off, s; 651 652 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 653 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 654 for (s = off; s < off+dof; ++s) { 655 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 656 } 657 } 658 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 659 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 660 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 661 for (p = pStart; p < pEnd; ++p) { 662 PetscInt dof, off, c; 663 664 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 665 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 666 for (c = off; c < off+dof; ++c) { 667 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 668 } 669 } 670 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 671 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 672 if (coordSection && coordinates) { 673 ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr); 674 } 675 ierr = DMGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 676 if (markers) {ierr = DMLabelView(markers,viewer);CHKERRQ(ierr);} 677 if (size > 1) { 678 PetscSF sf; 679 680 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 681 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 682 } 683 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 684 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 685 const char *name, *color; 686 const char *defcolors[3] = {"gray", "orange", "green"}; 687 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 688 char lname[PETSC_MAX_PATH_LEN]; 689 PetscReal scale = 2.0; 690 PetscReal tikzscale = 1.0; 691 PetscBool useNumbers = PETSC_TRUE, useLabels, useColors; 692 double tcoords[3]; 693 PetscScalar *coords; 694 PetscInt numLabels, l, numColors, numLColors, dim, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 695 PetscMPIInt rank, size; 696 char **names, **colors, **lcolors; 697 PetscBool plotEdges, flg, lflg; 698 PetscBT wp = NULL; 699 PetscInt pEnd, pStart; 700 701 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 702 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 703 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 704 numLabels = PetscMax(numLabels, 10); 705 numColors = 10; 706 numLColors = 10; 707 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 708 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 709 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 710 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 711 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 712 if (!useLabels) numLabels = 0; 713 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 714 if (!useColors) { 715 numColors = 3; 716 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 717 } 718 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 719 if (!useColors) { 720 numLColors = 4; 721 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 722 } 723 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, PETSC_MAX_PATH_LEN, &lflg);CHKERRQ(ierr); 724 plotEdges = (PetscBool)(depth > 1 && useNumbers && dim < 3); 725 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 726 if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 727 if (depth < dim) plotEdges = PETSC_FALSE; 728 729 /* filter points with labelvalue != labeldefaultvalue */ 730 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 731 if (lflg) { 732 DMLabel lbl; 733 734 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 735 if (lbl) { 736 PetscInt val, defval; 737 738 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 739 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 740 for (c = pStart; c < pEnd; c++) { 741 PetscInt *closure = NULL; 742 PetscInt closureSize; 743 744 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 745 if (val == defval) continue; 746 747 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 748 for (p = 0; p < closureSize*2; p += 2) { 749 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 750 } 751 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 752 } 753 } 754 } 755 756 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 757 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 758 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 759 ierr = PetscViewerASCIIPrintf(viewer, "\ 760 \\documentclass[tikz]{standalone}\n\n\ 761 \\usepackage{pgflibraryshapes}\n\ 762 \\usetikzlibrary{backgrounds}\n\ 763 \\usetikzlibrary{arrows}\n\ 764 \\begin{document}\n");CHKERRQ(ierr); 765 if (size > 1) { 766 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 767 for (p = 0; p < size; ++p) { 768 if (p > 0 && p == size-1) { 769 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 770 } else if (p > 0) { 771 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 772 } 773 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 774 } 775 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 776 } 777 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 778 779 /* Plot vertices */ 780 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 781 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 782 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 783 for (v = vStart; v < vEnd; ++v) { 784 PetscInt off, dof, d; 785 PetscBool isLabeled = PETSC_FALSE; 786 787 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 788 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 789 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 790 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 791 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 792 for (d = 0; d < dof; ++d) { 793 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 794 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 795 } 796 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 797 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 798 for (d = 0; d < dof; ++d) { 799 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 800 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 801 } 802 color = colors[rank%numColors]; 803 for (l = 0; l < numLabels; ++l) { 804 PetscInt val; 805 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 806 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 807 } 808 if (useNumbers) { 809 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 810 } else { 811 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 812 } 813 } 814 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 815 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 816 /* Plot cells */ 817 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 818 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 819 if (dim == 3 || !useNumbers) { 820 for (e = eStart; e < eEnd; ++e) { 821 const PetscInt *cone; 822 823 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 824 color = colors[rank%numColors]; 825 for (l = 0; l < numLabels; ++l) { 826 PetscInt val; 827 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 828 if (val >= 0) {color = lcolors[l%numLColors]; break;} 829 } 830 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 831 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 832 } 833 } else { 834 for (c = cStart; c < cEnd; ++c) { 835 PetscInt *closure = NULL; 836 PetscInt closureSize, firstPoint = -1; 837 838 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 839 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 840 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 841 for (p = 0; p < closureSize*2; p += 2) { 842 const PetscInt point = closure[p]; 843 844 if ((point < vStart) || (point >= vEnd)) continue; 845 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 846 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", point, rank);CHKERRQ(ierr); 847 if (firstPoint < 0) firstPoint = point; 848 } 849 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 850 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d);\n", firstPoint, rank);CHKERRQ(ierr); 851 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 852 } 853 } 854 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 855 for (c = cStart; c < cEnd; ++c) { 856 double ccoords[3] = {0.0, 0.0, 0.0}; 857 PetscBool isLabeled = PETSC_FALSE; 858 PetscInt *closure = NULL; 859 PetscInt closureSize, dof, d, n = 0; 860 861 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 862 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 863 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 864 for (p = 0; p < closureSize*2; p += 2) { 865 const PetscInt point = closure[p]; 866 PetscInt off; 867 868 if ((point < vStart) || (point >= vEnd)) continue; 869 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 870 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 871 for (d = 0; d < dof; ++d) { 872 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 873 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 874 } 875 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 876 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 877 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 878 ++n; 879 } 880 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 881 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 882 for (d = 0; d < dof; ++d) { 883 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 884 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 885 } 886 color = colors[rank%numColors]; 887 for (l = 0; l < numLabels; ++l) { 888 PetscInt val; 889 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 890 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 891 } 892 if (useNumbers) { 893 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 894 } else { 895 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 896 } 897 } 898 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 899 /* Plot edges */ 900 if (plotEdges) { 901 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 902 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 903 for (e = eStart; e < eEnd; ++e) { 904 const PetscInt *cone; 905 PetscInt coneSize, offA, offB, dof, d; 906 907 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 908 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 909 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 910 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 911 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 912 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 913 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 914 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 915 for (d = 0; d < dof; ++d) { 916 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 917 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 918 } 919 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 920 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 921 for (d = 0; d < dof; ++d) { 922 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 923 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 924 } 925 color = colors[rank%numColors]; 926 for (l = 0; l < numLabels; ++l) { 927 PetscInt val; 928 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 929 if (val >= 0) {color = lcolors[l%numLColors]; break;} 930 } 931 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 932 } 933 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 934 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 935 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 936 } 937 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 938 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 939 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 940 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 941 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 942 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 943 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 944 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 945 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 946 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 947 Vec cown,acown; 948 VecScatter sct; 949 ISLocalToGlobalMapping g2l; 950 IS gid,acis; 951 MPI_Comm comm,ncomm = MPI_COMM_NULL; 952 MPI_Group ggroup,ngroup; 953 PetscScalar *array,nid; 954 const PetscInt *idxs; 955 PetscInt *idxs2,*start,*adjacency,*work; 956 PetscInt64 lm[3],gm[3]; 957 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 958 PetscMPIInt d1,d2,rank; 959 960 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 961 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 962 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 963 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRQ(ierr); 964 #endif 965 if (ncomm != MPI_COMM_NULL) { 966 ierr = MPI_Comm_group(comm,&ggroup);CHKERRQ(ierr); 967 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRQ(ierr); 968 d1 = 0; 969 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRQ(ierr); 970 nid = d2; 971 ierr = MPI_Group_free(&ggroup);CHKERRQ(ierr); 972 ierr = MPI_Group_free(&ngroup);CHKERRQ(ierr); 973 ierr = MPI_Comm_free(&ncomm);CHKERRQ(ierr); 974 } else nid = 0.0; 975 976 /* Get connectivity */ 977 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 978 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 979 980 /* filter overlapped local cells */ 981 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 982 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 983 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 984 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 985 for (c = cStart, cum = 0; c < cEnd; c++) { 986 if (idxs[c-cStart] < 0) continue; 987 idxs2[cum++] = idxs[c-cStart]; 988 } 989 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 990 if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 991 ierr = ISDestroy(&gid);CHKERRQ(ierr); 992 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 993 994 /* support for node-aware cell locality */ 995 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 996 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 997 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 998 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 999 for (c = 0; c < numVertices; c++) array[c] = nid; 1000 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1001 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1002 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1003 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1004 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1005 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1006 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1007 1008 /* compute edgeCut */ 1009 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1010 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1011 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1012 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1013 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1014 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1015 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1016 PetscInt totl; 1017 1018 totl = start[c+1]-start[c]; 1019 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1020 for (i = 0; i < totl; i++) { 1021 if (work[i] < 0) { 1022 ect += 1; 1023 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1024 } 1025 } 1026 } 1027 ierr = PetscFree(work);CHKERRQ(ierr); 1028 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1029 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1030 lm[1] = -numVertices; 1031 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRQ(ierr); 1032 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1033 lm[0] = ect; /* edgeCut */ 1034 lm[1] = ectn; /* node-aware edgeCut */ 1035 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1036 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRQ(ierr); 1037 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1038 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1039 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),gm[0] ? ((double)(gm[1]))/((double)gm[0]) : 1.);CHKERRQ(ierr); 1040 #else 1041 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1042 #endif 1043 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1044 ierr = PetscFree(start);CHKERRQ(ierr); 1045 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1046 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1047 } else { 1048 MPI_Comm comm; 1049 PetscInt *sizes, *hybsizes, *ghostsizes; 1050 PetscInt locDepth, depth, cellHeight, dim, d, pMax[4]; 1051 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1052 PetscInt numLabels, l; 1053 const char *name; 1054 PetscMPIInt size; 1055 1056 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1057 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1058 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1059 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1060 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1061 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1062 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1063 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1064 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1065 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 1066 ierr = DMPlexGetHybridBounds(dm, &pMax[depth], depth > 0 ? &pMax[depth-1] : NULL, depth > 1 ? &pMax[depth - 2] : NULL, &pMax[0]);CHKERRQ(ierr); 1067 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1068 gcNum = gcEnd - gcStart; 1069 ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr); 1070 if (depth == 1) { 1071 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 1072 pEnd = pEnd - pStart; 1073 pMax[0] -= pStart; 1074 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1075 ierr = MPI_Gather(&pMax[0], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1076 ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1077 ierr = PetscViewerASCIIPrintf(viewer, " %d-cells:", 0);CHKERRQ(ierr); 1078 for (p = 0; p < size; ++p) { 1079 if (hybsizes[p] >= 0) {ierr = PetscViewerASCIIPrintf(viewer, " %D (%D)", sizes[p], sizes[p] - hybsizes[p]);CHKERRQ(ierr);} 1080 else {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 1081 } 1082 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1083 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 1084 pEnd = pEnd - pStart; 1085 pMax[depth] -= pStart; 1086 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1087 ierr = MPI_Gather(&pMax[depth], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1088 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 1089 for (p = 0; p < size; ++p) { 1090 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr); 1091 if (hybsizes[p] >= 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", sizes[p] - hybsizes[p]);CHKERRQ(ierr);} 1092 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1093 } 1094 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1095 } else { 1096 PetscMPIInt rank; 1097 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1098 for (d = 0; d <= dim; d++) { 1099 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1100 pEnd -= pStart; 1101 pMax[d] -= pStart; 1102 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1103 ierr = MPI_Gather(&pMax[d], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1104 if (d == dim) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);} 1105 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 1106 for (p = 0; p < size; ++p) { 1107 if (!rank) { 1108 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr); 1109 if (hybsizes[p] >= 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", sizes[p] - hybsizes[p]);CHKERRQ(ierr);} 1110 if (d == dim && ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1111 } 1112 } 1113 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1114 } 1115 } 1116 ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr); 1117 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1118 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1119 for (l = 0; l < numLabels; ++l) { 1120 DMLabel label; 1121 const char *name; 1122 IS valueIS; 1123 const PetscInt *values; 1124 PetscInt numValues, v; 1125 1126 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1127 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1128 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1129 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1130 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1131 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1132 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1133 for (v = 0; v < numValues; ++v) { 1134 PetscInt size; 1135 1136 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1137 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1138 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1139 } 1140 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1141 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1142 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1143 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1144 } 1145 /* If no fields are specified, people do not want to see adjacency */ 1146 if (dm->Nf) { 1147 PetscInt f; 1148 1149 for (f = 0; f < dm->Nf; ++f) { 1150 const char *name; 1151 1152 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1153 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1154 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1155 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1156 if (dm->fields[f].adjacency[0]) { 1157 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1158 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1159 } else { 1160 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1161 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1162 } 1163 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1164 } 1165 } 1166 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1167 if (cdm) { 1168 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1169 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1170 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1171 } 1172 } 1173 PetscFunctionReturn(0); 1174 } 1175 1176 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1177 { 1178 PetscDraw draw; 1179 DM cdm; 1180 PetscSection coordSection; 1181 Vec coordinates; 1182 const PetscScalar *coords; 1183 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1184 PetscBool isnull; 1185 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N; 1186 PetscMPIInt rank; 1187 PetscErrorCode ierr; 1188 1189 PetscFunctionBegin; 1190 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1191 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1192 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1193 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1194 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1195 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1196 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1197 1198 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1199 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1200 if (isnull) PetscFunctionReturn(0); 1201 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1202 1203 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1204 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1205 for (c = 0; c < N; c += dim) { 1206 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1207 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1208 } 1209 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1210 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1211 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1212 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1213 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1214 1215 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1216 for (c = cStart; c < cEnd; ++c) { 1217 PetscScalar *coords = NULL; 1218 DMPolytopeType ct; 1219 PetscInt numCoords; 1220 1221 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 1222 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1223 switch (ct) { 1224 case DM_POLYTOPE_TRIANGLE: 1225 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1226 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1227 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1228 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1229 break; 1230 case DM_POLYTOPE_QUADRILATERAL: 1231 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1232 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1233 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1234 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1235 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1236 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1237 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1238 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1239 break; 1240 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1241 } 1242 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1243 } 1244 for (c = cStart; c < cEnd; ++c) { 1245 PetscScalar *coords = NULL; 1246 DMPolytopeType ct; 1247 PetscInt numCoords; 1248 1249 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 1250 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1251 switch (ct) { 1252 case DM_POLYTOPE_TRIANGLE: 1253 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1254 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1255 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1256 break; 1257 case DM_POLYTOPE_QUADRILATERAL: 1258 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1259 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1260 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1261 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1262 break; 1263 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1264 } 1265 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1266 } 1267 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1268 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1269 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1270 PetscFunctionReturn(0); 1271 } 1272 1273 #if defined(PETSC_HAVE_EXODUSII) 1274 #include <exodusII.h> 1275 #endif 1276 1277 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1278 { 1279 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1280 char name[PETSC_MAX_PATH_LEN]; 1281 PetscErrorCode ierr; 1282 1283 PetscFunctionBegin; 1284 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1285 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1286 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1287 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1288 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1289 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1290 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1291 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1292 if (iascii) { 1293 PetscViewerFormat format; 1294 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1295 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1296 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1297 } else { 1298 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1299 } 1300 } else if (ishdf5) { 1301 #if defined(PETSC_HAVE_HDF5) 1302 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1303 #else 1304 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1305 #endif 1306 } else if (isvtk) { 1307 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1308 } else if (isdraw) { 1309 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1310 } else if (isglvis) { 1311 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1312 #if defined(PETSC_HAVE_EXODUSII) 1313 } else if (isexodus) { 1314 int exoid; 1315 PetscInt cStart, cEnd, c; 1316 1317 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1318 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1319 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1320 ierr = PetscViewerExodusIIGetId(viewer, &exoid);CHKERRQ(ierr); 1321 ierr = DMPlexView_ExodusII_Internal(dm, exoid, 1);CHKERRQ(ierr); 1322 #endif 1323 } else { 1324 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1325 } 1326 /* Optionally view the partition */ 1327 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1328 if (flg) { 1329 Vec ranks; 1330 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1331 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1332 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1333 } 1334 /* Optionally view a label */ 1335 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, PETSC_MAX_PATH_LEN, &flg);CHKERRQ(ierr); 1336 if (flg) { 1337 DMLabel label; 1338 Vec val; 1339 1340 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1341 if (!label) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1342 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1343 ierr = VecView(val, viewer);CHKERRQ(ierr); 1344 ierr = VecDestroy(&val);CHKERRQ(ierr); 1345 } 1346 PetscFunctionReturn(0); 1347 } 1348 1349 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1350 { 1351 PetscBool ishdf5; 1352 PetscErrorCode ierr; 1353 1354 PetscFunctionBegin; 1355 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1356 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1357 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1358 if (ishdf5) { 1359 #if defined(PETSC_HAVE_HDF5) 1360 PetscViewerFormat format; 1361 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1362 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 1363 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 1364 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1365 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1366 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1367 #else 1368 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1369 #endif 1370 } else { 1371 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 1372 } 1373 PetscFunctionReturn(0); 1374 } 1375 1376 PetscErrorCode DMDestroy_Plex(DM dm) 1377 { 1378 DM_Plex *mesh = (DM_Plex*) dm->data; 1379 PetscErrorCode ierr; 1380 1381 PetscFunctionBegin; 1382 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 1383 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 1384 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 1385 if (--mesh->refct > 0) PetscFunctionReturn(0); 1386 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 1387 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 1388 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 1389 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 1390 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 1391 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 1392 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 1393 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 1394 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 1395 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 1396 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 1397 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 1398 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 1399 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 1400 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 1401 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 1402 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 1403 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 1404 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 1405 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 1406 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 1407 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 1408 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 1409 ierr = PetscFree(mesh);CHKERRQ(ierr); 1410 PetscFunctionReturn(0); 1411 } 1412 1413 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 1414 { 1415 PetscSection sectionGlobal; 1416 PetscInt bs = -1, mbs; 1417 PetscInt localSize; 1418 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 1419 PetscErrorCode ierr; 1420 MatType mtype; 1421 ISLocalToGlobalMapping ltog; 1422 1423 PetscFunctionBegin; 1424 ierr = MatInitializePackage();CHKERRQ(ierr); 1425 mtype = dm->mattype; 1426 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1427 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 1428 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 1429 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 1430 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1431 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 1432 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1433 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 1434 if (mbs > 1) bs = mbs; 1435 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 1436 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 1437 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 1438 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 1439 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 1440 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 1441 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 1442 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 1443 if (!isShell) { 1444 PetscSection subSection; 1445 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 1446 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 1447 PetscInt pStart, pEnd, p, dof, cdof; 1448 1449 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 1450 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 1451 PetscSection section; 1452 PetscInt size; 1453 1454 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1455 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 1456 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 1457 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 1458 } else { 1459 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 1460 } 1461 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1462 for (p = pStart, lsize = 0; p < pEnd; ++p) { 1463 PetscInt bdof; 1464 1465 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1466 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 1467 dof = dof < 0 ? -(dof+1) : dof; 1468 bdof = cdof && (dof-cdof) ? 1 : dof; 1469 if (dof) { 1470 if (bs < 0) {bs = bdof;} 1471 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 1472 } 1473 if (isMatIS) { 1474 PetscInt loff,c,off; 1475 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 1476 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 1477 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 1478 } 1479 } 1480 /* Must have same blocksize on all procs (some might have no points) */ 1481 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 1482 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 1483 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 1484 else {bs = bsMinMax[0];} 1485 bs = PetscMax(1,bs); 1486 if (isMatIS) { /* Must reduce indices by blocksize */ 1487 PetscInt l; 1488 1489 lsize = lsize/bs; 1490 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 1491 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 1492 } 1493 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 1494 if (isMatIS) { 1495 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 1496 } 1497 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 1498 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1499 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1500 } 1501 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 1502 PetscFunctionReturn(0); 1503 } 1504 1505 /*@ 1506 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 1507 1508 Not collective 1509 1510 Input Parameter: 1511 . mesh - The DMPlex 1512 1513 Output Parameters: 1514 . subsection - The subdomain section 1515 1516 Level: developer 1517 1518 .seealso: 1519 @*/ 1520 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 1521 { 1522 DM_Plex *mesh = (DM_Plex*) dm->data; 1523 PetscErrorCode ierr; 1524 1525 PetscFunctionBegin; 1526 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1527 if (!mesh->subdomainSection) { 1528 PetscSection section; 1529 PetscSF sf; 1530 1531 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 1532 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 1533 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 1534 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 1535 } 1536 *subsection = mesh->subdomainSection; 1537 PetscFunctionReturn(0); 1538 } 1539 1540 /*@ 1541 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1542 1543 Not collective 1544 1545 Input Parameter: 1546 . mesh - The DMPlex 1547 1548 Output Parameters: 1549 + pStart - The first mesh point 1550 - pEnd - The upper bound for mesh points 1551 1552 Level: beginner 1553 1554 .seealso: DMPlexCreate(), DMPlexSetChart() 1555 @*/ 1556 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1557 { 1558 DM_Plex *mesh = (DM_Plex*) dm->data; 1559 PetscErrorCode ierr; 1560 1561 PetscFunctionBegin; 1562 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1563 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1564 PetscFunctionReturn(0); 1565 } 1566 1567 /*@ 1568 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1569 1570 Not collective 1571 1572 Input Parameters: 1573 + mesh - The DMPlex 1574 . pStart - The first mesh point 1575 - pEnd - The upper bound for mesh points 1576 1577 Output Parameters: 1578 1579 Level: beginner 1580 1581 .seealso: DMPlexCreate(), DMPlexGetChart() 1582 @*/ 1583 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1584 { 1585 DM_Plex *mesh = (DM_Plex*) dm->data; 1586 PetscErrorCode ierr; 1587 1588 PetscFunctionBegin; 1589 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1590 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1591 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1592 PetscFunctionReturn(0); 1593 } 1594 1595 /*@ 1596 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 1597 1598 Not collective 1599 1600 Input Parameters: 1601 + mesh - The DMPlex 1602 - p - The point, which must lie in the chart set with DMPlexSetChart() 1603 1604 Output Parameter: 1605 . size - The cone size for point p 1606 1607 Level: beginner 1608 1609 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1610 @*/ 1611 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1612 { 1613 DM_Plex *mesh = (DM_Plex*) dm->data; 1614 PetscErrorCode ierr; 1615 1616 PetscFunctionBegin; 1617 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1618 PetscValidPointer(size, 3); 1619 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1620 PetscFunctionReturn(0); 1621 } 1622 1623 /*@ 1624 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 1625 1626 Not collective 1627 1628 Input Parameters: 1629 + mesh - The DMPlex 1630 . p - The point, which must lie in the chart set with DMPlexSetChart() 1631 - size - The cone size for point p 1632 1633 Output Parameter: 1634 1635 Note: 1636 This should be called after DMPlexSetChart(). 1637 1638 Level: beginner 1639 1640 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1641 @*/ 1642 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1643 { 1644 DM_Plex *mesh = (DM_Plex*) dm->data; 1645 PetscErrorCode ierr; 1646 1647 PetscFunctionBegin; 1648 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1649 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1650 1651 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1652 PetscFunctionReturn(0); 1653 } 1654 1655 /*@ 1656 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 1657 1658 Not collective 1659 1660 Input Parameters: 1661 + mesh - The DMPlex 1662 . p - The point, which must lie in the chart set with DMPlexSetChart() 1663 - size - The additional cone size for point p 1664 1665 Output Parameter: 1666 1667 Note: 1668 This should be called after DMPlexSetChart(). 1669 1670 Level: beginner 1671 1672 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 1673 @*/ 1674 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 1675 { 1676 DM_Plex *mesh = (DM_Plex*) dm->data; 1677 PetscInt csize; 1678 PetscErrorCode ierr; 1679 1680 PetscFunctionBegin; 1681 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1682 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1683 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 1684 1685 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 1686 PetscFunctionReturn(0); 1687 } 1688 1689 /*@C 1690 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 1691 1692 Not collective 1693 1694 Input Parameters: 1695 + dm - The DMPlex 1696 - p - The point, which must lie in the chart set with DMPlexSetChart() 1697 1698 Output Parameter: 1699 . cone - An array of points which are on the in-edges for point p 1700 1701 Level: beginner 1702 1703 Fortran Notes: 1704 Since it returns an array, this routine is only available in Fortran 90, and you must 1705 include petsc.h90 in your code. 1706 You must also call DMPlexRestoreCone() after you finish using the returned array. 1707 DMPlexRestoreCone() is not needed/available in C. 1708 1709 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 1710 @*/ 1711 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1712 { 1713 DM_Plex *mesh = (DM_Plex*) dm->data; 1714 PetscInt off; 1715 PetscErrorCode ierr; 1716 1717 PetscFunctionBegin; 1718 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1719 PetscValidPointer(cone, 3); 1720 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1721 *cone = &mesh->cones[off]; 1722 PetscFunctionReturn(0); 1723 } 1724 1725 /*@C 1726 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 1727 1728 Not collective 1729 1730 Input Parameters: 1731 + dm - The DMPlex 1732 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 1733 1734 Output Parameter: 1735 + pConesSection - PetscSection describing the layout of pCones 1736 - pCones - An array of points which are on the in-edges for the point set p 1737 1738 Level: intermediate 1739 1740 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 1741 @*/ 1742 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 1743 { 1744 PetscSection cs, newcs; 1745 PetscInt *cones; 1746 PetscInt *newarr=NULL; 1747 PetscInt n; 1748 PetscErrorCode ierr; 1749 1750 PetscFunctionBegin; 1751 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 1752 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 1753 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 1754 if (pConesSection) *pConesSection = newcs; 1755 if (pCones) { 1756 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 1757 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 1758 } 1759 PetscFunctionReturn(0); 1760 } 1761 1762 /*@ 1763 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 1764 1765 Not collective 1766 1767 Input Parameters: 1768 + dm - The DMPlex 1769 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 1770 1771 Output Parameter: 1772 . expandedPoints - An array of vertices recursively expanded from input points 1773 1774 Level: advanced 1775 1776 Notes: 1777 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 1778 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 1779 1780 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 1781 @*/ 1782 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 1783 { 1784 IS *expandedPointsAll; 1785 PetscInt depth; 1786 PetscErrorCode ierr; 1787 1788 PetscFunctionBegin; 1789 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1790 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 1791 PetscValidPointer(expandedPoints, 3); 1792 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 1793 *expandedPoints = expandedPointsAll[0]; 1794 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]); 1795 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 1796 PetscFunctionReturn(0); 1797 } 1798 1799 /*@ 1800 DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices (DAG points of depth 0, i.e. without cones). 1801 1802 Not collective 1803 1804 Input Parameters: 1805 + dm - The DMPlex 1806 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 1807 1808 Output Parameter: 1809 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 1810 . expandedPoints - (optional) An array of index sets with recursively expanded cones 1811 - sections - (optional) An array of sections which describe mappings from points to their cone points 1812 1813 Level: advanced 1814 1815 Notes: 1816 Like DMPlexGetConeTuple() but recursive. 1817 1818 Array expandedPoints has size equal to depth. Each expandedPoints[d] contains DAG points with maximum depth d, recursively cone-wise expanded from the input points. 1819 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 1820 1821 Array section has size equal to depth. Each PetscSection sections[d] realizes mapping from expandedPoints[d+1] (section points) to expandedPoints[d] (section dofs) as follows: 1822 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 1823 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 1824 1825 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 1826 @*/ 1827 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 1828 { 1829 const PetscInt *arr0=NULL, *cone=NULL; 1830 PetscInt *arr=NULL, *newarr=NULL; 1831 PetscInt d, depth_, i, n, newn, cn, co, start, end; 1832 IS *expandedPoints_; 1833 PetscSection *sections_; 1834 PetscErrorCode ierr; 1835 1836 PetscFunctionBegin; 1837 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1838 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 1839 if (depth) PetscValidIntPointer(depth, 3); 1840 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 1841 if (sections) PetscValidPointer(sections, 5); 1842 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 1843 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 1844 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 1845 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 1846 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 1847 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 1848 for (d=depth_-1; d>=0; d--) { 1849 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 1850 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 1851 for (i=0; i<n; i++) { 1852 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 1853 if (arr[i] >= start && arr[i] < end) { 1854 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 1855 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 1856 } else { 1857 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 1858 } 1859 } 1860 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 1861 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 1862 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 1863 for (i=0; i<n; i++) { 1864 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 1865 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 1866 if (cn > 1) { 1867 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 1868 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 1869 } else { 1870 newarr[co] = arr[i]; 1871 } 1872 } 1873 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 1874 arr = newarr; 1875 n = newn; 1876 } 1877 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 1878 *depth = depth_; 1879 if (expandedPoints) *expandedPoints = expandedPoints_; 1880 else { 1881 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 1882 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 1883 } 1884 if (sections) *sections = sections_; 1885 else { 1886 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 1887 ierr = PetscFree(sections_);CHKERRQ(ierr); 1888 } 1889 PetscFunctionReturn(0); 1890 } 1891 1892 /*@ 1893 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 1894 1895 Not collective 1896 1897 Input Parameters: 1898 + dm - The DMPlex 1899 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 1900 1901 Output Parameter: 1902 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 1903 . expandedPoints - (optional) An array of recursively expanded cones 1904 - sections - (optional) An array of sections which describe mappings from points to their cone points 1905 1906 Level: advanced 1907 1908 Notes: 1909 See DMPlexGetConeRecursive() for details. 1910 1911 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 1912 @*/ 1913 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 1914 { 1915 PetscInt d, depth_; 1916 PetscErrorCode ierr; 1917 1918 PetscFunctionBegin; 1919 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 1920 if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 1921 if (depth) *depth = 0; 1922 if (expandedPoints) { 1923 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 1924 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 1925 } 1926 if (sections) { 1927 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 1928 ierr = PetscFree(*sections);CHKERRQ(ierr); 1929 } 1930 PetscFunctionReturn(0); 1931 } 1932 1933 /*@ 1934 DMPlexSetCone - Set the points on the in-edges for this point in the DAG; that is these are the points that cover the specific point 1935 1936 Not collective 1937 1938 Input Parameters: 1939 + mesh - The DMPlex 1940 . p - The point, which must lie in the chart set with DMPlexSetChart() 1941 - cone - An array of points which are on the in-edges for point p 1942 1943 Output Parameter: 1944 1945 Note: 1946 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1947 1948 Developer Note: Why not call this DMPlexSetCover() 1949 1950 Level: beginner 1951 1952 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 1953 @*/ 1954 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1955 { 1956 DM_Plex *mesh = (DM_Plex*) dm->data; 1957 PetscInt pStart, pEnd; 1958 PetscInt dof, off, c; 1959 PetscErrorCode ierr; 1960 1961 PetscFunctionBegin; 1962 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1963 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1964 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1965 if (dof) PetscValidPointer(cone, 3); 1966 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1967 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); 1968 for (c = 0; c < dof; ++c) { 1969 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); 1970 mesh->cones[off+c] = cone[c]; 1971 } 1972 PetscFunctionReturn(0); 1973 } 1974 1975 /*@C 1976 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 1977 1978 Not collective 1979 1980 Input Parameters: 1981 + mesh - The DMPlex 1982 - p - The point, which must lie in the chart set with DMPlexSetChart() 1983 1984 Output Parameter: 1985 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1986 integer giving the prescription for cone traversal. If it is negative, the cone is 1987 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1988 the index of the cone point on which to start. 1989 1990 Level: beginner 1991 1992 Fortran Notes: 1993 Since it returns an array, this routine is only available in Fortran 90, and you must 1994 include petsc.h90 in your code. 1995 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 1996 DMPlexRestoreConeOrientation() is not needed/available in C. 1997 1998 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1999 @*/ 2000 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2001 { 2002 DM_Plex *mesh = (DM_Plex*) dm->data; 2003 PetscInt off; 2004 PetscErrorCode ierr; 2005 2006 PetscFunctionBegin; 2007 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2008 #if defined(PETSC_USE_DEBUG) 2009 { 2010 PetscInt dof; 2011 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2012 if (dof) PetscValidPointer(coneOrientation, 3); 2013 } 2014 #endif 2015 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2016 2017 *coneOrientation = &mesh->coneOrientations[off]; 2018 PetscFunctionReturn(0); 2019 } 2020 2021 /*@ 2022 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2023 2024 Not collective 2025 2026 Input Parameters: 2027 + mesh - The DMPlex 2028 . p - The point, which must lie in the chart set with DMPlexSetChart() 2029 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2030 integer giving the prescription for cone traversal. If it is negative, the cone is 2031 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2032 the index of the cone point on which to start. 2033 2034 Output Parameter: 2035 2036 Note: 2037 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2038 2039 Level: beginner 2040 2041 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2042 @*/ 2043 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 2044 { 2045 DM_Plex *mesh = (DM_Plex*) dm->data; 2046 PetscInt pStart, pEnd; 2047 PetscInt dof, off, c; 2048 PetscErrorCode ierr; 2049 2050 PetscFunctionBegin; 2051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2052 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2053 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2054 if (dof) PetscValidPointer(coneOrientation, 3); 2055 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2056 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); 2057 for (c = 0; c < dof; ++c) { 2058 PetscInt cdof, o = coneOrientation[c]; 2059 2060 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 2061 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); 2062 mesh->coneOrientations[off+c] = o; 2063 } 2064 PetscFunctionReturn(0); 2065 } 2066 2067 /*@ 2068 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 2069 2070 Not collective 2071 2072 Input Parameters: 2073 + mesh - The DMPlex 2074 . p - The point, which must lie in the chart set with DMPlexSetChart() 2075 . conePos - The local index in the cone where the point should be put 2076 - conePoint - The mesh point to insert 2077 2078 Level: beginner 2079 2080 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2081 @*/ 2082 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 2083 { 2084 DM_Plex *mesh = (DM_Plex*) dm->data; 2085 PetscInt pStart, pEnd; 2086 PetscInt dof, off; 2087 PetscErrorCode ierr; 2088 2089 PetscFunctionBegin; 2090 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2091 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2092 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); 2093 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); 2094 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2095 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2096 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); 2097 mesh->cones[off+conePos] = conePoint; 2098 PetscFunctionReturn(0); 2099 } 2100 2101 /*@ 2102 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 2103 2104 Not collective 2105 2106 Input Parameters: 2107 + mesh - The DMPlex 2108 . p - The point, which must lie in the chart set with DMPlexSetChart() 2109 . conePos - The local index in the cone where the point should be put 2110 - coneOrientation - The point orientation to insert 2111 2112 Level: beginner 2113 2114 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2115 @*/ 2116 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 2117 { 2118 DM_Plex *mesh = (DM_Plex*) dm->data; 2119 PetscInt pStart, pEnd; 2120 PetscInt dof, off; 2121 PetscErrorCode ierr; 2122 2123 PetscFunctionBegin; 2124 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2125 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2126 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); 2127 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2128 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2129 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); 2130 mesh->coneOrientations[off+conePos] = coneOrientation; 2131 PetscFunctionReturn(0); 2132 } 2133 2134 /*@ 2135 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 2136 2137 Not collective 2138 2139 Input Parameters: 2140 + mesh - The DMPlex 2141 - p - The point, which must lie in the chart set with DMPlexSetChart() 2142 2143 Output Parameter: 2144 . size - The support size for point p 2145 2146 Level: beginner 2147 2148 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 2149 @*/ 2150 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 2151 { 2152 DM_Plex *mesh = (DM_Plex*) dm->data; 2153 PetscErrorCode ierr; 2154 2155 PetscFunctionBegin; 2156 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2157 PetscValidPointer(size, 3); 2158 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2159 PetscFunctionReturn(0); 2160 } 2161 2162 /*@ 2163 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 2164 2165 Not collective 2166 2167 Input Parameters: 2168 + mesh - The DMPlex 2169 . p - The point, which must lie in the chart set with DMPlexSetChart() 2170 - size - The support size for point p 2171 2172 Output Parameter: 2173 2174 Note: 2175 This should be called after DMPlexSetChart(). 2176 2177 Level: beginner 2178 2179 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 2180 @*/ 2181 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 2182 { 2183 DM_Plex *mesh = (DM_Plex*) dm->data; 2184 PetscErrorCode ierr; 2185 2186 PetscFunctionBegin; 2187 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2188 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2189 2190 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 2191 PetscFunctionReturn(0); 2192 } 2193 2194 /*@C 2195 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 2196 2197 Not collective 2198 2199 Input Parameters: 2200 + mesh - The DMPlex 2201 - p - The point, which must lie in the chart set with DMPlexSetChart() 2202 2203 Output Parameter: 2204 . support - An array of points which are on the out-edges for point p 2205 2206 Level: beginner 2207 2208 Fortran Notes: 2209 Since it returns an array, this routine is only available in Fortran 90, and you must 2210 include petsc.h90 in your code. 2211 You must also call DMPlexRestoreSupport() after you finish using the returned array. 2212 DMPlexRestoreSupport() is not needed/available in C. 2213 2214 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2215 @*/ 2216 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 2217 { 2218 DM_Plex *mesh = (DM_Plex*) dm->data; 2219 PetscInt off; 2220 PetscErrorCode ierr; 2221 2222 PetscFunctionBegin; 2223 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2224 PetscValidPointer(support, 3); 2225 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2226 *support = &mesh->supports[off]; 2227 PetscFunctionReturn(0); 2228 } 2229 2230 /*@ 2231 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 2232 2233 Not collective 2234 2235 Input Parameters: 2236 + mesh - The DMPlex 2237 . p - The point, which must lie in the chart set with DMPlexSetChart() 2238 - support - An array of points which are on the out-edges for point p 2239 2240 Output Parameter: 2241 2242 Note: 2243 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 2244 2245 Level: beginner 2246 2247 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 2248 @*/ 2249 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 2250 { 2251 DM_Plex *mesh = (DM_Plex*) dm->data; 2252 PetscInt pStart, pEnd; 2253 PetscInt dof, off, c; 2254 PetscErrorCode ierr; 2255 2256 PetscFunctionBegin; 2257 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2258 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 2259 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2260 if (dof) PetscValidPointer(support, 3); 2261 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2262 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); 2263 for (c = 0; c < dof; ++c) { 2264 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); 2265 mesh->supports[off+c] = support[c]; 2266 } 2267 PetscFunctionReturn(0); 2268 } 2269 2270 /*@ 2271 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 2272 2273 Not collective 2274 2275 Input Parameters: 2276 + mesh - The DMPlex 2277 . p - The point, which must lie in the chart set with DMPlexSetChart() 2278 . supportPos - The local index in the cone where the point should be put 2279 - supportPoint - The mesh point to insert 2280 2281 Level: beginner 2282 2283 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2284 @*/ 2285 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 2286 { 2287 DM_Plex *mesh = (DM_Plex*) dm->data; 2288 PetscInt pStart, pEnd; 2289 PetscInt dof, off; 2290 PetscErrorCode ierr; 2291 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2294 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 2295 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2296 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2297 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); 2298 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); 2299 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); 2300 mesh->supports[off+supportPos] = supportPoint; 2301 PetscFunctionReturn(0); 2302 } 2303 2304 /*@C 2305 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 2306 2307 Not collective 2308 2309 Input Parameters: 2310 + mesh - The DMPlex 2311 . p - The point, which must lie in the chart set with DMPlexSetChart() 2312 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 2313 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 2314 2315 Output Parameters: 2316 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 2317 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 2318 2319 Note: 2320 If using internal storage (points is NULL on input), each call overwrites the last output. 2321 2322 Fortran Notes: 2323 Since it returns an array, this routine is only available in Fortran 90, and you must 2324 include petsc.h90 in your code. 2325 2326 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2327 2328 Level: beginner 2329 2330 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2331 @*/ 2332 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 2333 { 2334 DM_Plex *mesh = (DM_Plex*) dm->data; 2335 PetscInt *closure, *fifo; 2336 const PetscInt *tmp = NULL, *tmpO = NULL; 2337 PetscInt tmpSize, t; 2338 PetscInt depth = 0, maxSize; 2339 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 2340 PetscErrorCode ierr; 2341 2342 PetscFunctionBegin; 2343 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2344 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2345 /* This is only 1-level */ 2346 if (useCone) { 2347 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 2348 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 2349 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 2350 } else { 2351 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 2352 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 2353 } 2354 if (depth == 1) { 2355 if (*points) { 2356 closure = *points; 2357 } else { 2358 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 2359 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2360 } 2361 closure[0] = p; closure[1] = 0; 2362 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 2363 closure[closureSize] = tmp[t]; 2364 closure[closureSize+1] = tmpO ? tmpO[t] : 0; 2365 } 2366 if (numPoints) *numPoints = closureSize/2; 2367 if (points) *points = closure; 2368 PetscFunctionReturn(0); 2369 } 2370 { 2371 PetscInt c, coneSeries, s,supportSeries; 2372 2373 c = mesh->maxConeSize; 2374 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 2375 s = mesh->maxSupportSize; 2376 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 2377 maxSize = 2*PetscMax(coneSeries,supportSeries); 2378 } 2379 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2380 if (*points) { 2381 closure = *points; 2382 } else { 2383 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2384 } 2385 closure[0] = p; closure[1] = 0; 2386 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 2387 const PetscInt cp = tmp[t]; 2388 const PetscInt co = tmpO ? tmpO[t] : 0; 2389 2390 closure[closureSize] = cp; 2391 closure[closureSize+1] = co; 2392 fifo[fifoSize] = cp; 2393 fifo[fifoSize+1] = co; 2394 } 2395 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 2396 while (fifoSize - fifoStart) { 2397 const PetscInt q = fifo[fifoStart]; 2398 const PetscInt o = fifo[fifoStart+1]; 2399 const PetscInt rev = o >= 0 ? 0 : 1; 2400 const PetscInt off = rev ? -(o+1) : o; 2401 2402 if (useCone) { 2403 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 2404 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 2405 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 2406 } else { 2407 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 2408 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 2409 tmpO = NULL; 2410 } 2411 for (t = 0; t < tmpSize; ++t) { 2412 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 2413 const PetscInt cp = tmp[i]; 2414 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 2415 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 2416 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 2417 PetscInt co = tmpO ? tmpO[i] : 0; 2418 PetscInt c; 2419 2420 if (rev) { 2421 PetscInt childSize, coff; 2422 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 2423 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 2424 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 2425 } 2426 /* Check for duplicate */ 2427 for (c = 0; c < closureSize; c += 2) { 2428 if (closure[c] == cp) break; 2429 } 2430 if (c == closureSize) { 2431 closure[closureSize] = cp; 2432 closure[closureSize+1] = co; 2433 fifo[fifoSize] = cp; 2434 fifo[fifoSize+1] = co; 2435 closureSize += 2; 2436 fifoSize += 2; 2437 } 2438 } 2439 fifoStart += 2; 2440 } 2441 if (numPoints) *numPoints = closureSize/2; 2442 if (points) *points = closure; 2443 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2444 PetscFunctionReturn(0); 2445 } 2446 2447 /*@C 2448 DMPlexGetTransitiveClosure_Internal - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG with a specified initial orientation 2449 2450 Not collective 2451 2452 Input Parameters: 2453 + mesh - The DMPlex 2454 . p - The point, which must lie in the chart set with DMPlexSetChart() 2455 . orientation - The orientation of the point 2456 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 2457 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 2458 2459 Output Parameters: 2460 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 2461 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 2462 2463 Note: 2464 If using internal storage (points is NULL on input), each call overwrites the last output. 2465 2466 Fortran Notes: 2467 Since it returns an array, this routine is only available in Fortran 90, and you must 2468 include petsc.h90 in your code. 2469 2470 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2471 2472 Level: beginner 2473 2474 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2475 @*/ 2476 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 2477 { 2478 DM_Plex *mesh = (DM_Plex*) dm->data; 2479 PetscInt *closure, *fifo; 2480 const PetscInt *tmp = NULL, *tmpO = NULL; 2481 PetscInt tmpSize, t; 2482 PetscInt depth = 0, maxSize; 2483 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 2484 PetscErrorCode ierr; 2485 2486 PetscFunctionBegin; 2487 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2488 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2489 /* This is only 1-level */ 2490 if (useCone) { 2491 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 2492 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 2493 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 2494 } else { 2495 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 2496 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 2497 } 2498 if (depth == 1) { 2499 if (*points) { 2500 closure = *points; 2501 } else { 2502 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 2503 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2504 } 2505 closure[0] = p; closure[1] = ornt; 2506 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 2507 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 2508 closure[closureSize] = tmp[i]; 2509 closure[closureSize+1] = tmpO ? tmpO[i] : 0; 2510 } 2511 if (numPoints) *numPoints = closureSize/2; 2512 if (points) *points = closure; 2513 PetscFunctionReturn(0); 2514 } 2515 { 2516 PetscInt c, coneSeries, s,supportSeries; 2517 2518 c = mesh->maxConeSize; 2519 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 2520 s = mesh->maxSupportSize; 2521 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 2522 maxSize = 2*PetscMax(coneSeries,supportSeries); 2523 } 2524 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2525 if (*points) { 2526 closure = *points; 2527 } else { 2528 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2529 } 2530 closure[0] = p; closure[1] = ornt; 2531 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 2532 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 2533 const PetscInt cp = tmp[i]; 2534 PetscInt co = tmpO ? tmpO[i] : 0; 2535 2536 if (ornt < 0) { 2537 PetscInt childSize, coff; 2538 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 2539 coff = co < 0 ? -(tmpO[i]+1) : tmpO[i]; 2540 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 2541 } 2542 closure[closureSize] = cp; 2543 closure[closureSize+1] = co; 2544 fifo[fifoSize] = cp; 2545 fifo[fifoSize+1] = co; 2546 } 2547 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 2548 while (fifoSize - fifoStart) { 2549 const PetscInt q = fifo[fifoStart]; 2550 const PetscInt o = fifo[fifoStart+1]; 2551 const PetscInt rev = o >= 0 ? 0 : 1; 2552 const PetscInt off = rev ? -(o+1) : o; 2553 2554 if (useCone) { 2555 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 2556 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 2557 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 2558 } else { 2559 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 2560 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 2561 tmpO = NULL; 2562 } 2563 for (t = 0; t < tmpSize; ++t) { 2564 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 2565 const PetscInt cp = tmp[i]; 2566 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 2567 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 2568 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 2569 PetscInt co = tmpO ? tmpO[i] : 0; 2570 PetscInt c; 2571 2572 if (rev) { 2573 PetscInt childSize, coff; 2574 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 2575 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 2576 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 2577 } 2578 /* Check for duplicate */ 2579 for (c = 0; c < closureSize; c += 2) { 2580 if (closure[c] == cp) break; 2581 } 2582 if (c == closureSize) { 2583 closure[closureSize] = cp; 2584 closure[closureSize+1] = co; 2585 fifo[fifoSize] = cp; 2586 fifo[fifoSize+1] = co; 2587 closureSize += 2; 2588 fifoSize += 2; 2589 } 2590 } 2591 fifoStart += 2; 2592 } 2593 if (numPoints) *numPoints = closureSize/2; 2594 if (points) *points = closure; 2595 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2596 PetscFunctionReturn(0); 2597 } 2598 2599 /*@C 2600 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 2601 2602 Not collective 2603 2604 Input Parameters: 2605 + mesh - The DMPlex 2606 . p - The point, which must lie in the chart set with DMPlexSetChart() 2607 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 2608 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 2609 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 2610 2611 Note: 2612 If not using internal storage (points is not NULL on input), this call is unnecessary 2613 2614 Fortran Notes: 2615 Since it returns an array, this routine is only available in Fortran 90, and you must 2616 include petsc.h90 in your code. 2617 2618 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2619 2620 Level: beginner 2621 2622 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2623 @*/ 2624 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 2625 { 2626 PetscErrorCode ierr; 2627 2628 PetscFunctionBegin; 2629 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2630 if (numPoints) PetscValidIntPointer(numPoints,4); 2631 if (points) PetscValidPointer(points,5); 2632 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 2633 if (numPoints) *numPoints = 0; 2634 PetscFunctionReturn(0); 2635 } 2636 2637 /*@ 2638 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 2639 2640 Not collective 2641 2642 Input Parameter: 2643 . mesh - The DMPlex 2644 2645 Output Parameters: 2646 + maxConeSize - The maximum number of in-edges 2647 - maxSupportSize - The maximum number of out-edges 2648 2649 Level: beginner 2650 2651 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2652 @*/ 2653 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 2654 { 2655 DM_Plex *mesh = (DM_Plex*) dm->data; 2656 2657 PetscFunctionBegin; 2658 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2659 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 2660 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 2661 PetscFunctionReturn(0); 2662 } 2663 2664 PetscErrorCode DMSetUp_Plex(DM dm) 2665 { 2666 DM_Plex *mesh = (DM_Plex*) dm->data; 2667 PetscInt size; 2668 PetscErrorCode ierr; 2669 2670 PetscFunctionBegin; 2671 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2672 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 2673 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 2674 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 2675 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 2676 if (mesh->maxSupportSize) { 2677 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 2678 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 2679 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 2680 } 2681 PetscFunctionReturn(0); 2682 } 2683 2684 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 2685 { 2686 PetscErrorCode ierr; 2687 2688 PetscFunctionBegin; 2689 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 2690 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 2691 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 2692 if (dm->useNatural && dm->sfMigration) { 2693 PetscSF sfMigrationInv,sfNatural; 2694 PetscSection section, sectionSeq; 2695 2696 (*subdm)->sfMigration = dm->sfMigration; 2697 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 2698 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 2699 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 2700 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 2701 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 2702 2703 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 2704 (*subdm)->sfNatural = sfNatural; 2705 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 2706 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 2707 } 2708 PetscFunctionReturn(0); 2709 } 2710 2711 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 2712 { 2713 PetscErrorCode ierr; 2714 PetscInt i = 0; 2715 2716 PetscFunctionBegin; 2717 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 2718 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 2719 (*superdm)->useNatural = PETSC_FALSE; 2720 for (i = 0; i < len; i++){ 2721 if (dms[i]->useNatural && dms[i]->sfMigration) { 2722 PetscSF sfMigrationInv,sfNatural; 2723 PetscSection section, sectionSeq; 2724 2725 (*superdm)->sfMigration = dms[i]->sfMigration; 2726 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 2727 (*superdm)->useNatural = PETSC_TRUE; 2728 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 2729 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 2730 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 2731 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 2732 2733 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 2734 (*superdm)->sfNatural = sfNatural; 2735 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 2736 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 2737 break; 2738 } 2739 } 2740 PetscFunctionReturn(0); 2741 } 2742 2743 /*@ 2744 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 2745 2746 Not collective 2747 2748 Input Parameter: 2749 . mesh - The DMPlex 2750 2751 Output Parameter: 2752 2753 Note: 2754 This should be called after all calls to DMPlexSetCone() 2755 2756 Level: beginner 2757 2758 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 2759 @*/ 2760 PetscErrorCode DMPlexSymmetrize(DM dm) 2761 { 2762 DM_Plex *mesh = (DM_Plex*) dm->data; 2763 PetscInt *offsets; 2764 PetscInt supportSize; 2765 PetscInt pStart, pEnd, p; 2766 PetscErrorCode ierr; 2767 2768 PetscFunctionBegin; 2769 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2770 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 2771 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 2772 /* Calculate support sizes */ 2773 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2774 for (p = pStart; p < pEnd; ++p) { 2775 PetscInt dof, off, c; 2776 2777 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2778 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2779 for (c = off; c < off+dof; ++c) { 2780 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 2781 } 2782 } 2783 for (p = pStart; p < pEnd; ++p) { 2784 PetscInt dof; 2785 2786 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2787 2788 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 2789 } 2790 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 2791 /* Calculate supports */ 2792 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 2793 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 2794 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 2795 for (p = pStart; p < pEnd; ++p) { 2796 PetscInt dof, off, c; 2797 2798 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2799 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2800 for (c = off; c < off+dof; ++c) { 2801 const PetscInt q = mesh->cones[c]; 2802 PetscInt offS; 2803 2804 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 2805 2806 mesh->supports[offS+offsets[q]] = p; 2807 ++offsets[q]; 2808 } 2809 } 2810 ierr = PetscFree(offsets);CHKERRQ(ierr); 2811 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 2812 PetscFunctionReturn(0); 2813 } 2814 2815 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 2816 { 2817 IS stratumIS; 2818 PetscErrorCode ierr; 2819 2820 PetscFunctionBegin; 2821 if (pStart >= pEnd) PetscFunctionReturn(0); 2822 #if defined(PETSC_USE_DEBUG) 2823 { 2824 PetscInt qStart, qEnd, numLevels, level; 2825 PetscBool overlap = PETSC_FALSE; 2826 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 2827 for (level = 0; level < numLevels; level++) { 2828 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 2829 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 2830 } 2831 if (overlap) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %D range [%D,%D) overlaps with depth %D range [%D,%D)", depth, pStart, pEnd, level, qStart, qEnd); 2832 } 2833 #endif 2834 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 2835 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 2836 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 2837 PetscFunctionReturn(0); 2838 } 2839 2840 static PetscErrorCode DMPlexCreateDimStratum(DM,DMLabel,DMLabel,PetscInt,PetscInt); 2841 2842 /*@ 2843 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 2844 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2845 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2846 the DAG. 2847 2848 Collective on dm 2849 2850 Input Parameter: 2851 . mesh - The DMPlex 2852 2853 Output Parameter: 2854 2855 Notes: 2856 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 2857 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 2858 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 2859 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 2860 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 2861 2862 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 2863 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 2864 we had a mesh consisting of one triangle (c0) and three vertices (v0, v1, v2), and only one edge is on the boundary so we choose 2865 to interpolate only that one (e0), so that 2866 $ cone(c0) = {e0, v2} 2867 $ cone(e0) = {v0, v1} 2868 If DMPlexStratify() is run on this mesh, it will give depths 2869 $ depth 0 = {v0, v1, v2} 2870 $ depth 1 = {e0, c0} 2871 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 2872 2873 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 2874 2875 Level: beginner 2876 2877 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 2878 @*/ 2879 PetscErrorCode DMPlexStratify(DM dm) 2880 { 2881 DM_Plex *mesh = (DM_Plex*) dm->data; 2882 DMLabel label; 2883 PetscInt pStart, pEnd, p; 2884 PetscInt numRoots = 0, numLeaves = 0; 2885 PetscInt cMax, fMax, eMax, vMax; 2886 PetscErrorCode ierr; 2887 2888 PetscFunctionBegin; 2889 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2890 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2891 2892 /* Create depth label */ 2893 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2894 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 2895 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2896 2897 { 2898 /* Initialize roots and count leaves */ 2899 PetscInt sMin = PETSC_MAX_INT; 2900 PetscInt sMax = PETSC_MIN_INT; 2901 PetscInt coneSize, supportSize; 2902 2903 for (p = pStart; p < pEnd; ++p) { 2904 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2905 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2906 if (!coneSize && supportSize) { 2907 sMin = PetscMin(p, sMin); 2908 sMax = PetscMax(p, sMax); 2909 ++numRoots; 2910 } else if (!supportSize && coneSize) { 2911 ++numLeaves; 2912 } else if (!supportSize && !coneSize) { 2913 /* Isolated points */ 2914 sMin = PetscMin(p, sMin); 2915 sMax = PetscMax(p, sMax); 2916 } 2917 } 2918 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 2919 } 2920 2921 if (numRoots + numLeaves == (pEnd - pStart)) { 2922 PetscInt sMin = PETSC_MAX_INT; 2923 PetscInt sMax = PETSC_MIN_INT; 2924 PetscInt coneSize, supportSize; 2925 2926 for (p = pStart; p < pEnd; ++p) { 2927 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2928 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2929 if (!supportSize && coneSize) { 2930 sMin = PetscMin(p, sMin); 2931 sMax = PetscMax(p, sMax); 2932 } 2933 } 2934 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 2935 } else { 2936 PetscInt level = 0; 2937 PetscInt qStart, qEnd, q; 2938 2939 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 2940 while (qEnd > qStart) { 2941 PetscInt sMin = PETSC_MAX_INT; 2942 PetscInt sMax = PETSC_MIN_INT; 2943 2944 for (q = qStart; q < qEnd; ++q) { 2945 const PetscInt *support; 2946 PetscInt supportSize, s; 2947 2948 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 2949 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 2950 for (s = 0; s < supportSize; ++s) { 2951 sMin = PetscMin(support[s], sMin); 2952 sMax = PetscMax(support[s], sMax); 2953 } 2954 } 2955 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 2956 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 2957 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 2958 } 2959 } 2960 { /* just in case there is an empty process */ 2961 PetscInt numValues, maxValues = 0, v; 2962 2963 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 2964 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 2965 for (v = numValues; v < maxValues; v++) { 2966 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 2967 } 2968 } 2969 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 2970 2971 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 2972 if (cMax >= 0 || fMax >= 0 || eMax >= 0 || vMax >= 0) { 2973 PetscInt dim; 2974 DMLabel dimLabel; 2975 2976 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2977 ierr = DMCreateLabel(dm, "dim");CHKERRQ(ierr); 2978 ierr = DMGetLabel(dm, "dim", &dimLabel);CHKERRQ(ierr); 2979 if (cMax >= 0) {ierr = DMPlexCreateDimStratum(dm, label, dimLabel, dim, cMax);CHKERRQ(ierr);} 2980 if (fMax >= 0) {ierr = DMPlexCreateDimStratum(dm, label, dimLabel, dim - 1, fMax);CHKERRQ(ierr);} 2981 if (eMax >= 0) {ierr = DMPlexCreateDimStratum(dm, label, dimLabel, 1, eMax);CHKERRQ(ierr);} 2982 if (vMax >= 0) {ierr = DMPlexCreateDimStratum(dm, label, dimLabel, 0, vMax);CHKERRQ(ierr);} 2983 } 2984 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2985 PetscFunctionReturn(0); 2986 } 2987 2988 /*@ 2989 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 2990 2991 Collective on dm 2992 2993 Input Parameter: 2994 . mesh - The DMPlex 2995 2996 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 2997 2998 Level: beginner 2999 3000 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify() 3001 @*/ 3002 PetscErrorCode DMPlexComputeCellTypes(DM dm) 3003 { 3004 DM_Plex *mesh; 3005 DMLabel label; 3006 PetscInt dim, depth, gcStart, gcEnd, pStart, pEnd, p; 3007 PetscErrorCode ierr; 3008 3009 PetscFunctionBegin; 3010 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3011 mesh = (DM_Plex *) dm->data; 3012 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 3013 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 3014 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3015 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3016 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3017 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 3018 for (p = pStart; p < pEnd; ++p) { 3019 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3020 PetscInt pdepth, pheight, coneSize; 3021 3022 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 3023 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3024 pheight = depth - pdepth; 3025 if (depth <= 1) { 3026 switch (pdepth) { 3027 case 0: ct = DM_POLYTOPE_POINT;break; 3028 case 1: 3029 switch (coneSize) { 3030 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3031 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3032 case 4: 3033 switch (dim) { 3034 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3035 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3036 default: break; 3037 } 3038 break; 3039 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3040 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 3041 default: break; 3042 } 3043 } 3044 } else { 3045 if (pdepth == 0) { 3046 ct = DM_POLYTOPE_POINT; 3047 } else if (pheight == 0) { 3048 if ((p >= gcStart) && (p < gcEnd)) { 3049 if (coneSize == 1) ct = DM_POLYTOPE_FV_GHOST; 3050 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Ghost cell %D should have a cone size of 1, not %D", p, coneSize); 3051 } else { 3052 switch (dim) { 3053 case 1: 3054 switch (coneSize) { 3055 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3056 default: break; 3057 } 3058 break; 3059 case 2: 3060 switch (coneSize) { 3061 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3062 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3063 default: break; 3064 } 3065 break; 3066 case 3: 3067 switch (coneSize) { 3068 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 3069 case 5: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3070 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 3071 default: break; 3072 } 3073 break; 3074 default: break; 3075 } 3076 } 3077 } else if (pheight > 0) { 3078 switch (coneSize) { 3079 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3080 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3081 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3082 default: break; 3083 } 3084 } 3085 } 3086 if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 3087 ierr = DMLabelSetValue(label, p, ct);CHKERRQ(ierr); 3088 } 3089 ierr = PetscObjectStateGet((PetscObject) label, &mesh->celltypeState);CHKERRQ(ierr); 3090 ierr = PetscObjectViewFromOptions((PetscObject) label, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 3091 PetscFunctionReturn(0); 3092 } 3093 3094 /*@C 3095 DMPlexGetJoin - Get an array for the join of the set of points 3096 3097 Not Collective 3098 3099 Input Parameters: 3100 + dm - The DMPlex object 3101 . numPoints - The number of input points for the join 3102 - points - The input points 3103 3104 Output Parameters: 3105 + numCoveredPoints - The number of points in the join 3106 - coveredPoints - The points in the join 3107 3108 Level: intermediate 3109 3110 Note: Currently, this is restricted to a single level join 3111 3112 Fortran Notes: 3113 Since it returns an array, this routine is only available in Fortran 90, and you must 3114 include petsc.h90 in your code. 3115 3116 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3117 3118 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 3119 @*/ 3120 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3121 { 3122 DM_Plex *mesh = (DM_Plex*) dm->data; 3123 PetscInt *join[2]; 3124 PetscInt joinSize, i = 0; 3125 PetscInt dof, off, p, c, m; 3126 PetscErrorCode ierr; 3127 3128 PetscFunctionBegin; 3129 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3130 PetscValidIntPointer(points, 3); 3131 PetscValidIntPointer(numCoveredPoints, 4); 3132 PetscValidPointer(coveredPoints, 5); 3133 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 3134 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3135 /* Copy in support of first point */ 3136 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 3137 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 3138 for (joinSize = 0; joinSize < dof; ++joinSize) { 3139 join[i][joinSize] = mesh->supports[off+joinSize]; 3140 } 3141 /* Check each successive support */ 3142 for (p = 1; p < numPoints; ++p) { 3143 PetscInt newJoinSize = 0; 3144 3145 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 3146 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 3147 for (c = 0; c < dof; ++c) { 3148 const PetscInt point = mesh->supports[off+c]; 3149 3150 for (m = 0; m < joinSize; ++m) { 3151 if (point == join[i][m]) { 3152 join[1-i][newJoinSize++] = point; 3153 break; 3154 } 3155 } 3156 } 3157 joinSize = newJoinSize; 3158 i = 1-i; 3159 } 3160 *numCoveredPoints = joinSize; 3161 *coveredPoints = join[i]; 3162 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 3163 PetscFunctionReturn(0); 3164 } 3165 3166 /*@C 3167 DMPlexRestoreJoin - Restore an array for the join of the set of points 3168 3169 Not Collective 3170 3171 Input Parameters: 3172 + dm - The DMPlex object 3173 . numPoints - The number of input points for the join 3174 - points - The input points 3175 3176 Output Parameters: 3177 + numCoveredPoints - The number of points in the join 3178 - coveredPoints - The points in the join 3179 3180 Fortran Notes: 3181 Since it returns an array, this routine is only available in Fortran 90, and you must 3182 include petsc.h90 in your code. 3183 3184 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3185 3186 Level: intermediate 3187 3188 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 3189 @*/ 3190 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3191 { 3192 PetscErrorCode ierr; 3193 3194 PetscFunctionBegin; 3195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3196 if (points) PetscValidIntPointer(points,3); 3197 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 3198 PetscValidPointer(coveredPoints, 5); 3199 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 3200 if (numCoveredPoints) *numCoveredPoints = 0; 3201 PetscFunctionReturn(0); 3202 } 3203 3204 /*@C 3205 DMPlexGetFullJoin - Get an array for the join of the set of points 3206 3207 Not Collective 3208 3209 Input Parameters: 3210 + dm - The DMPlex object 3211 . numPoints - The number of input points for the join 3212 - points - The input points 3213 3214 Output Parameters: 3215 + numCoveredPoints - The number of points in the join 3216 - coveredPoints - The points in the join 3217 3218 Fortran Notes: 3219 Since it returns an array, this routine is only available in Fortran 90, and you must 3220 include petsc.h90 in your code. 3221 3222 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3223 3224 Level: intermediate 3225 3226 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 3227 @*/ 3228 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3229 { 3230 DM_Plex *mesh = (DM_Plex*) dm->data; 3231 PetscInt *offsets, **closures; 3232 PetscInt *join[2]; 3233 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 3234 PetscInt p, d, c, m, ms; 3235 PetscErrorCode ierr; 3236 3237 PetscFunctionBegin; 3238 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3239 PetscValidIntPointer(points, 3); 3240 PetscValidIntPointer(numCoveredPoints, 4); 3241 PetscValidPointer(coveredPoints, 5); 3242 3243 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3244 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 3245 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3246 ms = mesh->maxSupportSize; 3247 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 3248 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 3249 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3250 3251 for (p = 0; p < numPoints; ++p) { 3252 PetscInt closureSize; 3253 3254 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 3255 3256 offsets[p*(depth+2)+0] = 0; 3257 for (d = 0; d < depth+1; ++d) { 3258 PetscInt pStart, pEnd, i; 3259 3260 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3261 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 3262 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 3263 offsets[p*(depth+2)+d+1] = i; 3264 break; 3265 } 3266 } 3267 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 3268 } 3269 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); 3270 } 3271 for (d = 0; d < depth+1; ++d) { 3272 PetscInt dof; 3273 3274 /* Copy in support of first point */ 3275 dof = offsets[d+1] - offsets[d]; 3276 for (joinSize = 0; joinSize < dof; ++joinSize) { 3277 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 3278 } 3279 /* Check each successive cone */ 3280 for (p = 1; p < numPoints && joinSize; ++p) { 3281 PetscInt newJoinSize = 0; 3282 3283 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 3284 for (c = 0; c < dof; ++c) { 3285 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 3286 3287 for (m = 0; m < joinSize; ++m) { 3288 if (point == join[i][m]) { 3289 join[1-i][newJoinSize++] = point; 3290 break; 3291 } 3292 } 3293 } 3294 joinSize = newJoinSize; 3295 i = 1-i; 3296 } 3297 if (joinSize) break; 3298 } 3299 *numCoveredPoints = joinSize; 3300 *coveredPoints = join[i]; 3301 for (p = 0; p < numPoints; ++p) { 3302 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 3303 } 3304 ierr = PetscFree(closures);CHKERRQ(ierr); 3305 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3306 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 3307 PetscFunctionReturn(0); 3308 } 3309 3310 /*@C 3311 DMPlexGetMeet - Get an array for the meet of the set of points 3312 3313 Not Collective 3314 3315 Input Parameters: 3316 + dm - The DMPlex object 3317 . numPoints - The number of input points for the meet 3318 - points - The input points 3319 3320 Output Parameters: 3321 + numCoveredPoints - The number of points in the meet 3322 - coveredPoints - The points in the meet 3323 3324 Level: intermediate 3325 3326 Note: Currently, this is restricted to a single level meet 3327 3328 Fortran Notes: 3329 Since it returns an array, this routine is only available in Fortran 90, and you must 3330 include petsc.h90 in your code. 3331 3332 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3333 3334 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 3335 @*/ 3336 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 3337 { 3338 DM_Plex *mesh = (DM_Plex*) dm->data; 3339 PetscInt *meet[2]; 3340 PetscInt meetSize, i = 0; 3341 PetscInt dof, off, p, c, m; 3342 PetscErrorCode ierr; 3343 3344 PetscFunctionBegin; 3345 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3346 PetscValidPointer(points, 2); 3347 PetscValidPointer(numCoveringPoints, 3); 3348 PetscValidPointer(coveringPoints, 4); 3349 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 3350 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 3351 /* Copy in cone of first point */ 3352 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 3353 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 3354 for (meetSize = 0; meetSize < dof; ++meetSize) { 3355 meet[i][meetSize] = mesh->cones[off+meetSize]; 3356 } 3357 /* Check each successive cone */ 3358 for (p = 1; p < numPoints; ++p) { 3359 PetscInt newMeetSize = 0; 3360 3361 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 3362 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 3363 for (c = 0; c < dof; ++c) { 3364 const PetscInt point = mesh->cones[off+c]; 3365 3366 for (m = 0; m < meetSize; ++m) { 3367 if (point == meet[i][m]) { 3368 meet[1-i][newMeetSize++] = point; 3369 break; 3370 } 3371 } 3372 } 3373 meetSize = newMeetSize; 3374 i = 1-i; 3375 } 3376 *numCoveringPoints = meetSize; 3377 *coveringPoints = meet[i]; 3378 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 3379 PetscFunctionReturn(0); 3380 } 3381 3382 /*@C 3383 DMPlexRestoreMeet - Restore an array for the meet of the set of points 3384 3385 Not Collective 3386 3387 Input Parameters: 3388 + dm - The DMPlex object 3389 . numPoints - The number of input points for the meet 3390 - points - The input points 3391 3392 Output Parameters: 3393 + numCoveredPoints - The number of points in the meet 3394 - coveredPoints - The points in the meet 3395 3396 Level: intermediate 3397 3398 Fortran Notes: 3399 Since it returns an array, this routine is only available in Fortran 90, and you must 3400 include petsc.h90 in your code. 3401 3402 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3403 3404 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 3405 @*/ 3406 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3407 { 3408 PetscErrorCode ierr; 3409 3410 PetscFunctionBegin; 3411 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3412 if (points) PetscValidIntPointer(points,3); 3413 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 3414 PetscValidPointer(coveredPoints,5); 3415 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 3416 if (numCoveredPoints) *numCoveredPoints = 0; 3417 PetscFunctionReturn(0); 3418 } 3419 3420 /*@C 3421 DMPlexGetFullMeet - Get an array for the meet of the set of points 3422 3423 Not Collective 3424 3425 Input Parameters: 3426 + dm - The DMPlex object 3427 . numPoints - The number of input points for the meet 3428 - points - The input points 3429 3430 Output Parameters: 3431 + numCoveredPoints - The number of points in the meet 3432 - coveredPoints - The points in the meet 3433 3434 Level: intermediate 3435 3436 Fortran Notes: 3437 Since it returns an array, this routine is only available in Fortran 90, and you must 3438 include petsc.h90 in your code. 3439 3440 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3441 3442 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 3443 @*/ 3444 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3445 { 3446 DM_Plex *mesh = (DM_Plex*) dm->data; 3447 PetscInt *offsets, **closures; 3448 PetscInt *meet[2]; 3449 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 3450 PetscInt p, h, c, m, mc; 3451 PetscErrorCode ierr; 3452 3453 PetscFunctionBegin; 3454 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3455 PetscValidPointer(points, 2); 3456 PetscValidPointer(numCoveredPoints, 3); 3457 PetscValidPointer(coveredPoints, 4); 3458 3459 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 3460 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 3461 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3462 mc = mesh->maxConeSize; 3463 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 3464 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 3465 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 3466 3467 for (p = 0; p < numPoints; ++p) { 3468 PetscInt closureSize; 3469 3470 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 3471 3472 offsets[p*(height+2)+0] = 0; 3473 for (h = 0; h < height+1; ++h) { 3474 PetscInt pStart, pEnd, i; 3475 3476 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 3477 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 3478 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 3479 offsets[p*(height+2)+h+1] = i; 3480 break; 3481 } 3482 } 3483 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 3484 } 3485 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); 3486 } 3487 for (h = 0; h < height+1; ++h) { 3488 PetscInt dof; 3489 3490 /* Copy in cone of first point */ 3491 dof = offsets[h+1] - offsets[h]; 3492 for (meetSize = 0; meetSize < dof; ++meetSize) { 3493 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 3494 } 3495 /* Check each successive cone */ 3496 for (p = 1; p < numPoints && meetSize; ++p) { 3497 PetscInt newMeetSize = 0; 3498 3499 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 3500 for (c = 0; c < dof; ++c) { 3501 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 3502 3503 for (m = 0; m < meetSize; ++m) { 3504 if (point == meet[i][m]) { 3505 meet[1-i][newMeetSize++] = point; 3506 break; 3507 } 3508 } 3509 } 3510 meetSize = newMeetSize; 3511 i = 1-i; 3512 } 3513 if (meetSize) break; 3514 } 3515 *numCoveredPoints = meetSize; 3516 *coveredPoints = meet[i]; 3517 for (p = 0; p < numPoints; ++p) { 3518 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 3519 } 3520 ierr = PetscFree(closures);CHKERRQ(ierr); 3521 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3522 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 3523 PetscFunctionReturn(0); 3524 } 3525 3526 /*@C 3527 DMPlexEqual - Determine if two DMs have the same topology 3528 3529 Not Collective 3530 3531 Input Parameters: 3532 + dmA - A DMPlex object 3533 - dmB - A DMPlex object 3534 3535 Output Parameters: 3536 . equal - PETSC_TRUE if the topologies are identical 3537 3538 Level: intermediate 3539 3540 Notes: 3541 We are not solving graph isomorphism, so we do not permutation. 3542 3543 .seealso: DMPlexGetCone() 3544 @*/ 3545 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 3546 { 3547 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 3548 PetscErrorCode ierr; 3549 3550 PetscFunctionBegin; 3551 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 3552 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 3553 PetscValidPointer(equal, 3); 3554 3555 *equal = PETSC_FALSE; 3556 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 3557 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 3558 if (depth != depthB) PetscFunctionReturn(0); 3559 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 3560 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 3561 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 3562 for (p = pStart; p < pEnd; ++p) { 3563 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 3564 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 3565 3566 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 3567 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 3568 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 3569 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 3570 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 3571 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 3572 if (coneSize != coneSizeB) PetscFunctionReturn(0); 3573 for (c = 0; c < coneSize; ++c) { 3574 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 3575 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 3576 } 3577 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 3578 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 3579 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 3580 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 3581 if (supportSize != supportSizeB) PetscFunctionReturn(0); 3582 for (s = 0; s < supportSize; ++s) { 3583 if (support[s] != supportB[s]) PetscFunctionReturn(0); 3584 } 3585 } 3586 *equal = PETSC_TRUE; 3587 PetscFunctionReturn(0); 3588 } 3589 3590 /*@C 3591 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 3592 3593 Not Collective 3594 3595 Input Parameters: 3596 + dm - The DMPlex 3597 . cellDim - The cell dimension 3598 - numCorners - The number of vertices on a cell 3599 3600 Output Parameters: 3601 . numFaceVertices - The number of vertices on a face 3602 3603 Level: developer 3604 3605 Notes: 3606 Of course this can only work for a restricted set of symmetric shapes 3607 3608 .seealso: DMPlexGetCone() 3609 @*/ 3610 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 3611 { 3612 MPI_Comm comm; 3613 PetscErrorCode ierr; 3614 3615 PetscFunctionBegin; 3616 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3617 PetscValidPointer(numFaceVertices,3); 3618 switch (cellDim) { 3619 case 0: 3620 *numFaceVertices = 0; 3621 break; 3622 case 1: 3623 *numFaceVertices = 1; 3624 break; 3625 case 2: 3626 switch (numCorners) { 3627 case 3: /* triangle */ 3628 *numFaceVertices = 2; /* Edge has 2 vertices */ 3629 break; 3630 case 4: /* quadrilateral */ 3631 *numFaceVertices = 2; /* Edge has 2 vertices */ 3632 break; 3633 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 3634 *numFaceVertices = 3; /* Edge has 3 vertices */ 3635 break; 3636 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 3637 *numFaceVertices = 3; /* Edge has 3 vertices */ 3638 break; 3639 default: 3640 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 3641 } 3642 break; 3643 case 3: 3644 switch (numCorners) { 3645 case 4: /* tetradehdron */ 3646 *numFaceVertices = 3; /* Face has 3 vertices */ 3647 break; 3648 case 6: /* tet cohesive cells */ 3649 *numFaceVertices = 4; /* Face has 4 vertices */ 3650 break; 3651 case 8: /* hexahedron */ 3652 *numFaceVertices = 4; /* Face has 4 vertices */ 3653 break; 3654 case 9: /* tet cohesive Lagrange cells */ 3655 *numFaceVertices = 6; /* Face has 6 vertices */ 3656 break; 3657 case 10: /* quadratic tetrahedron */ 3658 *numFaceVertices = 6; /* Face has 6 vertices */ 3659 break; 3660 case 12: /* hex cohesive Lagrange cells */ 3661 *numFaceVertices = 6; /* Face has 6 vertices */ 3662 break; 3663 case 18: /* quadratic tet cohesive Lagrange cells */ 3664 *numFaceVertices = 6; /* Face has 6 vertices */ 3665 break; 3666 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 3667 *numFaceVertices = 9; /* Face has 9 vertices */ 3668 break; 3669 default: 3670 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 3671 } 3672 break; 3673 default: 3674 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 3675 } 3676 PetscFunctionReturn(0); 3677 } 3678 3679 /*@ 3680 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 3681 3682 Not Collective 3683 3684 Input Parameter: 3685 . dm - The DMPlex object 3686 3687 Output Parameter: 3688 . depthLabel - The DMLabel recording point depth 3689 3690 Level: developer 3691 3692 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 3693 @*/ 3694 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 3695 { 3696 PetscFunctionBegin; 3697 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3698 PetscValidPointer(depthLabel, 2); 3699 *depthLabel = dm->depthLabel; 3700 PetscFunctionReturn(0); 3701 } 3702 3703 /*@ 3704 DMPlexGetDepth - Get the depth of the DAG representing this mesh 3705 3706 Not Collective 3707 3708 Input Parameter: 3709 . dm - The DMPlex object 3710 3711 Output Parameter: 3712 . depth - The number of strata (breadth first levels) in the DAG 3713 3714 Level: developer 3715 3716 Notes: 3717 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 3718 The point depth is described more in detail in DMPlexSymmetrize(). 3719 3720 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexGetPointHeight(), DMPlexSymmetrize() 3721 @*/ 3722 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 3723 { 3724 DMLabel label; 3725 PetscInt d = 0; 3726 PetscErrorCode ierr; 3727 3728 PetscFunctionBegin; 3729 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3730 PetscValidPointer(depth, 2); 3731 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3732 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 3733 *depth = d-1; 3734 PetscFunctionReturn(0); 3735 } 3736 3737 /*@ 3738 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 3739 3740 Not Collective 3741 3742 Input Parameters: 3743 + dm - The DMPlex object 3744 - stratumValue - The requested depth 3745 3746 Output Parameters: 3747 + start - The first point at this depth 3748 - end - One beyond the last point at this depth 3749 3750 Notes: 3751 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 3752 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 3753 higher dimension, e.g., "edges". 3754 3755 Level: developer 3756 3757 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetPointDepth() 3758 @*/ 3759 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 3760 { 3761 DMLabel label; 3762 PetscInt pStart, pEnd; 3763 PetscErrorCode ierr; 3764 3765 PetscFunctionBegin; 3766 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3767 if (start) {PetscValidPointer(start, 3); *start = 0;} 3768 if (end) {PetscValidPointer(end, 4); *end = 0;} 3769 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3770 if (pStart == pEnd) PetscFunctionReturn(0); 3771 if (stratumValue < 0) { 3772 if (start) *start = pStart; 3773 if (end) *end = pEnd; 3774 PetscFunctionReturn(0); 3775 } 3776 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3777 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 3778 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 3779 PetscFunctionReturn(0); 3780 } 3781 3782 /*@ 3783 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 3784 3785 Not Collective 3786 3787 Input Parameters: 3788 + dm - The DMPlex object 3789 - stratumValue - The requested height 3790 3791 Output Parameters: 3792 + start - The first point at this height 3793 - end - One beyond the last point at this height 3794 3795 Notes: 3796 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 3797 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 3798 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 3799 3800 Level: developer 3801 3802 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 3803 @*/ 3804 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 3805 { 3806 DMLabel label; 3807 PetscInt depth, pStart, pEnd; 3808 PetscErrorCode ierr; 3809 3810 PetscFunctionBegin; 3811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3812 if (start) {PetscValidPointer(start, 3); *start = 0;} 3813 if (end) {PetscValidPointer(end, 4); *end = 0;} 3814 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3815 if (pStart == pEnd) PetscFunctionReturn(0); 3816 if (stratumValue < 0) { 3817 if (start) *start = pStart; 3818 if (end) *end = pEnd; 3819 PetscFunctionReturn(0); 3820 } 3821 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3822 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 3823 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 3824 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 3825 PetscFunctionReturn(0); 3826 } 3827 3828 /*@ 3829 DMPlexGetPointDepth - Get the depth of a given point 3830 3831 Not Collective 3832 3833 Input Parameter: 3834 + dm - The DMPlex object 3835 - point - The point 3836 3837 Output Parameter: 3838 . depth - The depth of the point 3839 3840 Level: intermediate 3841 3842 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 3843 @*/ 3844 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 3845 { 3846 PetscErrorCode ierr; 3847 3848 PetscFunctionBegin; 3849 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3850 PetscValidIntPointer(depth, 3); 3851 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 3852 PetscFunctionReturn(0); 3853 } 3854 3855 /*@ 3856 DMPlexGetPointHeight - Get the height of a given point 3857 3858 Not Collective 3859 3860 Input Parameter: 3861 + dm - The DMPlex object 3862 - point - The point 3863 3864 Output Parameter: 3865 . height - The height of the point 3866 3867 Level: intermediate 3868 3869 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 3870 @*/ 3871 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 3872 { 3873 PetscInt n, pDepth; 3874 PetscErrorCode ierr; 3875 3876 PetscFunctionBegin; 3877 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3878 PetscValidIntPointer(height, 3); 3879 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 3880 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 3881 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 3882 PetscFunctionReturn(0); 3883 } 3884 3885 /*@ 3886 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 3887 3888 Not Collective 3889 3890 Input Parameter: 3891 . dm - The DMPlex object 3892 3893 Output Parameter: 3894 . celltypeLabel - The DMLabel recording cell polytope type 3895 3896 Level: developer 3897 3898 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth() 3899 @*/ 3900 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 3901 { 3902 PetscErrorCode ierr; 3903 3904 PetscFunctionBegin; 3905 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3906 PetscValidPointer(celltypeLabel, 2); 3907 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 3908 *celltypeLabel = dm->celltypeLabel; 3909 PetscFunctionReturn(0); 3910 } 3911 3912 /*@ 3913 DMPlexGetCellType - Get the polytope type of a given cell 3914 3915 Not Collective 3916 3917 Input Parameter: 3918 + dm - The DMPlex object 3919 - cell - The cell 3920 3921 Output Parameter: 3922 . celltype - The polytope type of the cell 3923 3924 Level: intermediate 3925 3926 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 3927 @*/ 3928 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 3929 { 3930 DMLabel label; 3931 PetscInt ct; 3932 PetscErrorCode ierr; 3933 3934 PetscFunctionBegin; 3935 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3936 PetscValidPointer(celltype, 3); 3937 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 3938 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 3939 *celltype = (DMPolytopeType) ct; 3940 PetscFunctionReturn(0); 3941 } 3942 3943 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 3944 { 3945 PetscSection section, s; 3946 Mat m; 3947 PetscInt maxHeight; 3948 PetscErrorCode ierr; 3949 3950 PetscFunctionBegin; 3951 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3952 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 3953 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 3954 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3955 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 3956 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3957 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 3958 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 3959 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 3960 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 3961 ierr = MatDestroy(&m);CHKERRQ(ierr); 3962 3963 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 3964 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 3965 PetscFunctionReturn(0); 3966 } 3967 3968 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 3969 { 3970 Vec coordsLocal; 3971 DM coordsDM; 3972 PetscErrorCode ierr; 3973 3974 PetscFunctionBegin; 3975 *field = NULL; 3976 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 3977 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 3978 if (coordsLocal && coordsDM) { 3979 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 3980 } 3981 PetscFunctionReturn(0); 3982 } 3983 3984 /*@C 3985 DMPlexGetConeSection - Return a section which describes the layout of cone data 3986 3987 Not Collective 3988 3989 Input Parameters: 3990 . dm - The DMPlex object 3991 3992 Output Parameter: 3993 . section - The PetscSection object 3994 3995 Level: developer 3996 3997 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 3998 @*/ 3999 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 4000 { 4001 DM_Plex *mesh = (DM_Plex*) dm->data; 4002 4003 PetscFunctionBegin; 4004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4005 if (section) *section = mesh->coneSection; 4006 PetscFunctionReturn(0); 4007 } 4008 4009 /*@C 4010 DMPlexGetSupportSection - Return a section which describes the layout of support data 4011 4012 Not Collective 4013 4014 Input Parameters: 4015 . dm - The DMPlex object 4016 4017 Output Parameter: 4018 . section - The PetscSection object 4019 4020 Level: developer 4021 4022 .seealso: DMPlexGetConeSection() 4023 @*/ 4024 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 4025 { 4026 DM_Plex *mesh = (DM_Plex*) dm->data; 4027 4028 PetscFunctionBegin; 4029 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4030 if (section) *section = mesh->supportSection; 4031 PetscFunctionReturn(0); 4032 } 4033 4034 /*@C 4035 DMPlexGetCones - Return cone data 4036 4037 Not Collective 4038 4039 Input Parameters: 4040 . dm - The DMPlex object 4041 4042 Output Parameter: 4043 . cones - The cone for each point 4044 4045 Level: developer 4046 4047 .seealso: DMPlexGetConeSection() 4048 @*/ 4049 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 4050 { 4051 DM_Plex *mesh = (DM_Plex*) dm->data; 4052 4053 PetscFunctionBegin; 4054 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4055 if (cones) *cones = mesh->cones; 4056 PetscFunctionReturn(0); 4057 } 4058 4059 /*@C 4060 DMPlexGetConeOrientations - Return cone orientation data 4061 4062 Not Collective 4063 4064 Input Parameters: 4065 . dm - The DMPlex object 4066 4067 Output Parameter: 4068 . coneOrientations - The cone orientation for each point 4069 4070 Level: developer 4071 4072 .seealso: DMPlexGetConeSection() 4073 @*/ 4074 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 4075 { 4076 DM_Plex *mesh = (DM_Plex*) dm->data; 4077 4078 PetscFunctionBegin; 4079 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4080 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 4081 PetscFunctionReturn(0); 4082 } 4083 4084 /******************************** FEM Support **********************************/ 4085 4086 /* 4087 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 4088 representing a line in the section. 4089 */ 4090 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 4091 { 4092 PetscErrorCode ierr; 4093 4094 PetscFunctionBeginHot; 4095 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 4096 if (line < 0) { 4097 *k = 0; 4098 *Nc = 0; 4099 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 4100 *k = 1; 4101 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 4102 /* An order k SEM disc has k-1 dofs on an edge */ 4103 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 4104 *k = *k / *Nc + 1; 4105 } 4106 PetscFunctionReturn(0); 4107 } 4108 4109 /*@ 4110 4111 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 4112 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 4113 section provided (or the section of the DM). 4114 4115 Input Parameters: 4116 + dm - The DM 4117 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 4118 - section - The PetscSection to reorder, or NULL for the default section 4119 4120 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 4121 degree of the basis. 4122 4123 Example: 4124 A typical interpolated single-quad mesh might order points as 4125 .vb 4126 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 4127 4128 v4 -- e6 -- v3 4129 | | 4130 e7 c0 e8 4131 | | 4132 v1 -- e5 -- v2 4133 .ve 4134 4135 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 4136 dofs in the order of points, e.g., 4137 .vb 4138 c0 -> [0,1,2,3] 4139 v1 -> [4] 4140 ... 4141 e5 -> [8, 9] 4142 .ve 4143 4144 which corresponds to the dofs 4145 .vb 4146 6 10 11 7 4147 13 2 3 15 4148 12 0 1 14 4149 4 8 9 5 4150 .ve 4151 4152 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 4153 .vb 4154 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 4155 .ve 4156 4157 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 4158 .vb 4159 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 4160 .ve 4161 4162 Level: developer 4163 4164 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 4165 @*/ 4166 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 4167 { 4168 DMLabel label; 4169 PetscInt *perm; 4170 PetscInt dim, depth = -1, eStart = -1, k, Nf, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 4171 PetscBool vertexchart; 4172 PetscErrorCode ierr; 4173 4174 PetscFunctionBegin; 4175 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4176 if (dim < 1) PetscFunctionReturn(0); 4177 if (point < 0) { 4178 PetscInt sStart,sEnd; 4179 4180 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 4181 point = sEnd-sStart ? sStart : point; 4182 } 4183 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4184 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 4185 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 4186 if (depth == 1) {eStart = point;} 4187 else if (depth == dim) { 4188 const PetscInt *cone; 4189 4190 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4191 if (dim == 2) eStart = cone[0]; 4192 else if (dim == 3) { 4193 const PetscInt *cone2; 4194 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 4195 eStart = cone2[0]; 4196 } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim); 4197 } else if (depth >= 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim); 4198 { /* Determine whether the chart covers all points or just vertices. */ 4199 PetscInt pStart,pEnd,cStart,cEnd; 4200 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 4201 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 4202 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */ 4203 else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 4204 } 4205 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4206 for (f = 0; f < Nf; ++f) { 4207 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4208 size += PetscPowInt(k+1, dim)*Nc; 4209 } 4210 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 4211 for (f = 0; f < Nf; ++f) { 4212 switch (dim) { 4213 case 1: 4214 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4215 /* 4216 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 4217 We want [ vtx0; edge of length k-1; vtx1 ] 4218 */ 4219 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 4220 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 4221 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 4222 foffset = offset; 4223 break; 4224 case 2: 4225 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 4226 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4227 /* The SEM order is 4228 4229 v_lb, {e_b}, v_rb, 4230 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 4231 v_lt, reverse {e_t}, v_rt 4232 */ 4233 { 4234 const PetscInt of = 0; 4235 const PetscInt oeb = of + PetscSqr(k-1); 4236 const PetscInt oer = oeb + (k-1); 4237 const PetscInt oet = oer + (k-1); 4238 const PetscInt oel = oet + (k-1); 4239 const PetscInt ovlb = oel + (k-1); 4240 const PetscInt ovrb = ovlb + 1; 4241 const PetscInt ovrt = ovrb + 1; 4242 const PetscInt ovlt = ovrt + 1; 4243 PetscInt o; 4244 4245 /* bottom */ 4246 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 4247 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4248 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 4249 /* middle */ 4250 for (i = 0; i < k-1; ++i) { 4251 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 4252 for (o = of+(k-1)*i; o < of+(k-1)*(i+1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4253 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 4254 } 4255 /* top */ 4256 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 4257 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4258 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 4259 foffset = offset; 4260 } 4261 break; 4262 case 3: 4263 /* The original hex closure is 4264 4265 {c, 4266 f_b, f_t, f_f, f_b, f_r, f_l, 4267 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 4268 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 4269 */ 4270 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4271 /* The SEM order is 4272 Bottom Slice 4273 v_blf, {e^{(k-1)-n}_bf}, v_brf, 4274 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 4275 v_blb, {e_bb}, v_brb, 4276 4277 Middle Slice (j) 4278 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 4279 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 4280 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 4281 4282 Top Slice 4283 v_tlf, {e_tf}, v_trf, 4284 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 4285 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 4286 */ 4287 { 4288 const PetscInt oc = 0; 4289 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 4290 const PetscInt oft = ofb + PetscSqr(k-1); 4291 const PetscInt off = oft + PetscSqr(k-1); 4292 const PetscInt ofk = off + PetscSqr(k-1); 4293 const PetscInt ofr = ofk + PetscSqr(k-1); 4294 const PetscInt ofl = ofr + PetscSqr(k-1); 4295 const PetscInt oebl = ofl + PetscSqr(k-1); 4296 const PetscInt oebb = oebl + (k-1); 4297 const PetscInt oebr = oebb + (k-1); 4298 const PetscInt oebf = oebr + (k-1); 4299 const PetscInt oetf = oebf + (k-1); 4300 const PetscInt oetr = oetf + (k-1); 4301 const PetscInt oetb = oetr + (k-1); 4302 const PetscInt oetl = oetb + (k-1); 4303 const PetscInt oerf = oetl + (k-1); 4304 const PetscInt oelf = oerf + (k-1); 4305 const PetscInt oelb = oelf + (k-1); 4306 const PetscInt oerb = oelb + (k-1); 4307 const PetscInt ovblf = oerb + (k-1); 4308 const PetscInt ovblb = ovblf + 1; 4309 const PetscInt ovbrb = ovblb + 1; 4310 const PetscInt ovbrf = ovbrb + 1; 4311 const PetscInt ovtlf = ovbrf + 1; 4312 const PetscInt ovtrf = ovtlf + 1; 4313 const PetscInt ovtrb = ovtrf + 1; 4314 const PetscInt ovtlb = ovtrb + 1; 4315 PetscInt o, n; 4316 4317 /* Bottom Slice */ 4318 /* bottom */ 4319 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 4320 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4321 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 4322 /* middle */ 4323 for (i = 0; i < k-1; ++i) { 4324 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 4325 for (n = 0; n < k-1; ++n) {o = ofb+n*(k-1)+i; for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;} 4326 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 4327 } 4328 /* top */ 4329 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 4330 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4331 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 4332 4333 /* Middle Slice */ 4334 for (j = 0; j < k-1; ++j) { 4335 /* bottom */ 4336 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 4337 for (o = off+j*(k-1); o < off+(j+1)*(k-1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4338 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 4339 /* middle */ 4340 for (i = 0; i < k-1; ++i) { 4341 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 4342 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc+(j*(k-1)+i)*(k-1)+n)*Nc + c + foffset; 4343 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 4344 } 4345 /* top */ 4346 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 4347 for (o = ofk+j*(k-1)+(k-2); o >= ofk+j*(k-1); --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4348 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 4349 } 4350 4351 /* Top Slice */ 4352 /* bottom */ 4353 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 4354 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4355 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 4356 /* middle */ 4357 for (i = 0; i < k-1; ++i) { 4358 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 4359 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 4360 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 4361 } 4362 /* top */ 4363 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 4364 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4365 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 4366 4367 foffset = offset; 4368 } 4369 break; 4370 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", dim); 4371 } 4372 } 4373 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 4374 /* Check permutation */ 4375 { 4376 PetscInt *check; 4377 4378 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 4379 for (i = 0; i < size; ++i) {check[i] = -1; if (perm[i] < 0 || perm[i] >= size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%D] = %D", i, perm[i]);} 4380 for (i = 0; i < size; ++i) check[perm[i]] = i; 4381 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 4382 ierr = PetscFree(check);CHKERRQ(ierr); 4383 } 4384 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 4385 PetscFunctionReturn(0); 4386 } 4387 4388 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 4389 { 4390 PetscDS prob; 4391 PetscInt depth, Nf, h; 4392 DMLabel label; 4393 PetscErrorCode ierr; 4394 4395 PetscFunctionBeginHot; 4396 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 4397 Nf = prob->Nf; 4398 label = dm->depthLabel; 4399 *dspace = NULL; 4400 if (field < Nf) { 4401 PetscObject disc = prob->disc[field]; 4402 4403 if (disc->classid == PETSCFE_CLASSID) { 4404 PetscDualSpace dsp; 4405 4406 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 4407 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 4408 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 4409 h = depth - 1 - h; 4410 if (h) { 4411 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 4412 } else { 4413 *dspace = dsp; 4414 } 4415 } 4416 } 4417 PetscFunctionReturn(0); 4418 } 4419 4420 4421 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4422 { 4423 PetscScalar *array, *vArray; 4424 const PetscInt *cone, *coneO; 4425 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 4426 PetscErrorCode ierr; 4427 4428 PetscFunctionBeginHot; 4429 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4430 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4431 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4432 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4433 if (!values || !*values) { 4434 if ((point >= pStart) && (point < pEnd)) { 4435 PetscInt dof; 4436 4437 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4438 size += dof; 4439 } 4440 for (p = 0; p < numPoints; ++p) { 4441 const PetscInt cp = cone[p]; 4442 PetscInt dof; 4443 4444 if ((cp < pStart) || (cp >= pEnd)) continue; 4445 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4446 size += dof; 4447 } 4448 if (!values) { 4449 if (csize) *csize = size; 4450 PetscFunctionReturn(0); 4451 } 4452 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 4453 } else { 4454 array = *values; 4455 } 4456 size = 0; 4457 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 4458 if ((point >= pStart) && (point < pEnd)) { 4459 PetscInt dof, off, d; 4460 PetscScalar *varr; 4461 4462 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4463 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4464 varr = &vArray[off]; 4465 for (d = 0; d < dof; ++d, ++offset) { 4466 array[offset] = varr[d]; 4467 } 4468 size += dof; 4469 } 4470 for (p = 0; p < numPoints; ++p) { 4471 const PetscInt cp = cone[p]; 4472 PetscInt o = coneO[p]; 4473 PetscInt dof, off, d; 4474 PetscScalar *varr; 4475 4476 if ((cp < pStart) || (cp >= pEnd)) continue; 4477 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4478 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 4479 varr = &vArray[off]; 4480 if (o >= 0) { 4481 for (d = 0; d < dof; ++d, ++offset) { 4482 array[offset] = varr[d]; 4483 } 4484 } else { 4485 for (d = dof-1; d >= 0; --d, ++offset) { 4486 array[offset] = varr[d]; 4487 } 4488 } 4489 size += dof; 4490 } 4491 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 4492 if (!*values) { 4493 if (csize) *csize = size; 4494 *values = array; 4495 } else { 4496 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4497 *csize = size; 4498 } 4499 PetscFunctionReturn(0); 4500 } 4501 4502 /* Compressed closure does not apply closure permutation */ 4503 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 4504 { 4505 const PetscInt *cla; 4506 PetscInt np, *pts = NULL; 4507 PetscErrorCode ierr; 4508 4509 PetscFunctionBeginHot; 4510 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 4511 if (!*clPoints) { 4512 PetscInt pStart, pEnd, p, q; 4513 4514 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4515 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 4516 /* Compress out points not in the section */ 4517 for (p = 0, q = 0; p < np; p++) { 4518 PetscInt r = pts[2*p]; 4519 if ((r >= pStart) && (r < pEnd)) { 4520 pts[q*2] = r; 4521 pts[q*2+1] = pts[2*p+1]; 4522 ++q; 4523 } 4524 } 4525 np = q; 4526 cla = NULL; 4527 } else { 4528 PetscInt dof, off; 4529 4530 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 4531 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 4532 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 4533 np = dof/2; 4534 pts = (PetscInt *) &cla[off]; 4535 } 4536 *numPoints = np; 4537 *points = pts; 4538 *clp = cla; 4539 4540 PetscFunctionReturn(0); 4541 } 4542 4543 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 4544 { 4545 PetscErrorCode ierr; 4546 4547 PetscFunctionBeginHot; 4548 if (!*clPoints) { 4549 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 4550 } else { 4551 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 4552 } 4553 *numPoints = 0; 4554 *points = NULL; 4555 *clSec = NULL; 4556 *clPoints = NULL; 4557 *clp = NULL; 4558 PetscFunctionReturn(0); 4559 } 4560 4561 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 4562 { 4563 PetscInt offset = 0, p; 4564 const PetscInt **perms = NULL; 4565 const PetscScalar **flips = NULL; 4566 PetscErrorCode ierr; 4567 4568 PetscFunctionBeginHot; 4569 *size = 0; 4570 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4571 for (p = 0; p < numPoints; p++) { 4572 const PetscInt point = points[2*p]; 4573 const PetscInt *perm = perms ? perms[p] : NULL; 4574 const PetscScalar *flip = flips ? flips[p] : NULL; 4575 PetscInt dof, off, d; 4576 const PetscScalar *varr; 4577 4578 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4579 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4580 varr = &vArray[off]; 4581 if (clperm) { 4582 if (perm) { 4583 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 4584 } else { 4585 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 4586 } 4587 if (flip) { 4588 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 4589 } 4590 } else { 4591 if (perm) { 4592 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 4593 } else { 4594 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 4595 } 4596 if (flip) { 4597 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 4598 } 4599 } 4600 offset += dof; 4601 } 4602 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4603 *size = offset; 4604 PetscFunctionReturn(0); 4605 } 4606 4607 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 4608 { 4609 PetscInt offset = 0, f; 4610 PetscErrorCode ierr; 4611 4612 PetscFunctionBeginHot; 4613 *size = 0; 4614 for (f = 0; f < numFields; ++f) { 4615 PetscInt p; 4616 const PetscInt **perms = NULL; 4617 const PetscScalar **flips = NULL; 4618 4619 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4620 for (p = 0; p < numPoints; p++) { 4621 const PetscInt point = points[2*p]; 4622 PetscInt fdof, foff, b; 4623 const PetscScalar *varr; 4624 const PetscInt *perm = perms ? perms[p] : NULL; 4625 const PetscScalar *flip = flips ? flips[p] : NULL; 4626 4627 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4628 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4629 varr = &vArray[foff]; 4630 if (clperm) { 4631 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 4632 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 4633 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 4634 } else { 4635 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 4636 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 4637 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 4638 } 4639 offset += fdof; 4640 } 4641 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4642 } 4643 *size = offset; 4644 PetscFunctionReturn(0); 4645 } 4646 4647 /*@C 4648 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 4649 4650 Not collective 4651 4652 Input Parameters: 4653 + dm - The DM 4654 . section - The section describing the layout in v, or NULL to use the default section 4655 . v - The local vector 4656 . point - The point in the DM 4657 . csize - The size of the input values array, or NULL 4658 - values - An array to use for the values, or NULL to have it allocated automatically 4659 4660 Output Parameters: 4661 + csize - The number of values in the closure 4662 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 4663 4664 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 4665 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 4666 $ assembly function, and a user may already have allocated storage for this operation. 4667 $ 4668 $ A typical use could be 4669 $ 4670 $ values = NULL; 4671 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4672 $ for (cl = 0; cl < clSize; ++cl) { 4673 $ <Compute on closure> 4674 $ } 4675 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4676 $ 4677 $ or 4678 $ 4679 $ PetscMalloc1(clMaxSize, &values); 4680 $ for (p = pStart; p < pEnd; ++p) { 4681 $ clSize = clMaxSize; 4682 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4683 $ for (cl = 0; cl < clSize; ++cl) { 4684 $ <Compute on closure> 4685 $ } 4686 $ } 4687 $ PetscFree(values); 4688 4689 Fortran Notes: 4690 Since it returns an array, this routine is only available in Fortran 90, and you must 4691 include petsc.h90 in your code. 4692 4693 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4694 4695 Level: intermediate 4696 4697 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4698 @*/ 4699 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4700 { 4701 PetscSection clSection; 4702 IS clPoints; 4703 PetscScalar *array; 4704 const PetscScalar *vArray; 4705 PetscInt *points = NULL; 4706 const PetscInt *clp, *perm; 4707 PetscInt depth, numFields, numPoints, size; 4708 PetscErrorCode ierr; 4709 4710 PetscFunctionBeginHot; 4711 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4712 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 4713 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4714 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4715 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4716 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4717 if (depth == 1 && numFields < 2) { 4718 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 4719 PetscFunctionReturn(0); 4720 } 4721 /* Get points */ 4722 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4723 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4724 /* Get array */ 4725 if (!values || !*values) { 4726 PetscInt asize = 0, dof, p; 4727 4728 for (p = 0; p < numPoints*2; p += 2) { 4729 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4730 asize += dof; 4731 } 4732 if (!values) { 4733 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4734 if (csize) *csize = asize; 4735 PetscFunctionReturn(0); 4736 } 4737 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 4738 } else { 4739 array = *values; 4740 } 4741 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 4742 /* Get values */ 4743 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 4744 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, array);CHKERRQ(ierr);} 4745 /* Cleanup points */ 4746 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4747 /* Cleanup array */ 4748 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 4749 if (!*values) { 4750 if (csize) *csize = size; 4751 *values = array; 4752 } else { 4753 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4754 *csize = size; 4755 } 4756 PetscFunctionReturn(0); 4757 } 4758 4759 /*@C 4760 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 4761 4762 Not collective 4763 4764 Input Parameters: 4765 + dm - The DM 4766 . section - The section describing the layout in v, or NULL to use the default section 4767 . v - The local vector 4768 . point - The point in the DM 4769 . csize - The number of values in the closure, or NULL 4770 - values - The array of values, which is a borrowed array and should not be freed 4771 4772 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 4773 4774 Fortran Notes: 4775 Since it returns an array, this routine is only available in Fortran 90, and you must 4776 include petsc.h90 in your code. 4777 4778 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4779 4780 Level: intermediate 4781 4782 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4783 @*/ 4784 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4785 { 4786 PetscInt size = 0; 4787 PetscErrorCode ierr; 4788 4789 PetscFunctionBegin; 4790 /* Should work without recalculating size */ 4791 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 4792 *values = NULL; 4793 PetscFunctionReturn(0); 4794 } 4795 4796 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 4797 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 4798 4799 PETSC_STATIC_INLINE PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 4800 { 4801 PetscInt cdof; /* The number of constraints on this point */ 4802 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4803 PetscScalar *a; 4804 PetscInt off, cind = 0, k; 4805 PetscErrorCode ierr; 4806 4807 PetscFunctionBegin; 4808 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4809 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4810 a = &array[off]; 4811 if (!cdof || setBC) { 4812 if (clperm) { 4813 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 4814 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 4815 } else { 4816 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 4817 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 4818 } 4819 } else { 4820 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4821 if (clperm) { 4822 if (perm) {for (k = 0; k < dof; ++k) { 4823 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4824 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4825 } 4826 } else { 4827 for (k = 0; k < dof; ++k) { 4828 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4829 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4830 } 4831 } 4832 } else { 4833 if (perm) { 4834 for (k = 0; k < dof; ++k) { 4835 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4836 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4837 } 4838 } else { 4839 for (k = 0; k < dof; ++k) { 4840 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4841 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4842 } 4843 } 4844 } 4845 } 4846 PetscFunctionReturn(0); 4847 } 4848 4849 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 4850 { 4851 PetscInt cdof; /* The number of constraints on this point */ 4852 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4853 PetscScalar *a; 4854 PetscInt off, cind = 0, k; 4855 PetscErrorCode ierr; 4856 4857 PetscFunctionBegin; 4858 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4859 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4860 a = &array[off]; 4861 if (cdof) { 4862 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4863 if (clperm) { 4864 if (perm) { 4865 for (k = 0; k < dof; ++k) { 4866 if ((cind < cdof) && (k == cdofs[cind])) { 4867 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4868 cind++; 4869 } 4870 } 4871 } else { 4872 for (k = 0; k < dof; ++k) { 4873 if ((cind < cdof) && (k == cdofs[cind])) { 4874 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4875 cind++; 4876 } 4877 } 4878 } 4879 } else { 4880 if (perm) { 4881 for (k = 0; k < dof; ++k) { 4882 if ((cind < cdof) && (k == cdofs[cind])) { 4883 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4884 cind++; 4885 } 4886 } 4887 } else { 4888 for (k = 0; k < dof; ++k) { 4889 if ((cind < cdof) && (k == cdofs[cind])) { 4890 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4891 cind++; 4892 } 4893 } 4894 } 4895 } 4896 } 4897 PetscFunctionReturn(0); 4898 } 4899 4900 PETSC_STATIC_INLINE PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, const PetscInt *perm, const PetscScalar *flip, PetscInt f, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 4901 { 4902 PetscScalar *a; 4903 PetscInt fdof, foff, fcdof, foffset = *offset; 4904 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4905 PetscInt cind = 0, b; 4906 PetscErrorCode ierr; 4907 4908 PetscFunctionBegin; 4909 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4910 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4911 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4912 a = &array[foff]; 4913 if (!fcdof || setBC) { 4914 if (clperm) { 4915 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 4916 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 4917 } else { 4918 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 4919 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 4920 } 4921 } else { 4922 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4923 if (clperm) { 4924 if (perm) { 4925 for (b = 0; b < fdof; b++) { 4926 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4927 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4928 } 4929 } else { 4930 for (b = 0; b < fdof; b++) { 4931 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4932 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4933 } 4934 } 4935 } else { 4936 if (perm) { 4937 for (b = 0; b < fdof; b++) { 4938 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4939 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4940 } 4941 } else { 4942 for (b = 0; b < fdof; b++) { 4943 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4944 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4945 } 4946 } 4947 } 4948 } 4949 *offset += fdof; 4950 PetscFunctionReturn(0); 4951 } 4952 4953 PETSC_STATIC_INLINE PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, const PetscInt perm[], const PetscScalar flip[], PetscInt f, PetscInt Ncc, const PetscInt comps[], void (*fuse)(PetscScalar*, PetscScalar), const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 4954 { 4955 PetscScalar *a; 4956 PetscInt fdof, foff, fcdof, foffset = *offset; 4957 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4958 PetscInt Nc, cind = 0, ncind = 0, b; 4959 PetscBool ncSet, fcSet; 4960 PetscErrorCode ierr; 4961 4962 PetscFunctionBegin; 4963 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 4964 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4965 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4966 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4967 a = &array[foff]; 4968 if (fcdof) { 4969 /* We just override fcdof and fcdofs with Ncc and comps */ 4970 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4971 if (clperm) { 4972 if (perm) { 4973 if (comps) { 4974 for (b = 0; b < fdof; b++) { 4975 ncSet = fcSet = PETSC_FALSE; 4976 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 4977 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4978 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 4979 } 4980 } else { 4981 for (b = 0; b < fdof; b++) { 4982 if ((cind < fcdof) && (b == fcdofs[cind])) { 4983 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4984 ++cind; 4985 } 4986 } 4987 } 4988 } else { 4989 if (comps) { 4990 for (b = 0; b < fdof; b++) { 4991 ncSet = fcSet = PETSC_FALSE; 4992 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 4993 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4994 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 4995 } 4996 } else { 4997 for (b = 0; b < fdof; b++) { 4998 if ((cind < fcdof) && (b == fcdofs[cind])) { 4999 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5000 ++cind; 5001 } 5002 } 5003 } 5004 } 5005 } else { 5006 if (perm) { 5007 if (comps) { 5008 for (b = 0; b < fdof; b++) { 5009 ncSet = fcSet = PETSC_FALSE; 5010 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5011 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5012 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 5013 } 5014 } else { 5015 for (b = 0; b < fdof; b++) { 5016 if ((cind < fcdof) && (b == fcdofs[cind])) { 5017 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 5018 ++cind; 5019 } 5020 } 5021 } 5022 } else { 5023 if (comps) { 5024 for (b = 0; b < fdof; b++) { 5025 ncSet = fcSet = PETSC_FALSE; 5026 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5027 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5028 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 5029 } 5030 } else { 5031 for (b = 0; b < fdof; b++) { 5032 if ((cind < fcdof) && (b == fcdofs[cind])) { 5033 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5034 ++cind; 5035 } 5036 } 5037 } 5038 } 5039 } 5040 } 5041 *offset += fdof; 5042 PetscFunctionReturn(0); 5043 } 5044 5045 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 5046 { 5047 PetscScalar *array; 5048 const PetscInt *cone, *coneO; 5049 PetscInt pStart, pEnd, p, numPoints, off, dof; 5050 PetscErrorCode ierr; 5051 5052 PetscFunctionBeginHot; 5053 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5054 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5055 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5056 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5057 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5058 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 5059 const PetscInt cp = !p ? point : cone[p-1]; 5060 const PetscInt o = !p ? 0 : coneO[p-1]; 5061 5062 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 5063 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5064 /* ADD_VALUES */ 5065 { 5066 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5067 PetscScalar *a; 5068 PetscInt cdof, coff, cind = 0, k; 5069 5070 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 5071 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 5072 a = &array[coff]; 5073 if (!cdof) { 5074 if (o >= 0) { 5075 for (k = 0; k < dof; ++k) { 5076 a[k] += values[off+k]; 5077 } 5078 } else { 5079 for (k = 0; k < dof; ++k) { 5080 a[k] += values[off+dof-k-1]; 5081 } 5082 } 5083 } else { 5084 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 5085 if (o >= 0) { 5086 for (k = 0; k < dof; ++k) { 5087 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5088 a[k] += values[off+k]; 5089 } 5090 } else { 5091 for (k = 0; k < dof; ++k) { 5092 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5093 a[k] += values[off+dof-k-1]; 5094 } 5095 } 5096 } 5097 } 5098 } 5099 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5100 PetscFunctionReturn(0); 5101 } 5102 5103 /*@C 5104 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 5105 5106 Not collective 5107 5108 Input Parameters: 5109 + dm - The DM 5110 . section - The section describing the layout in v, or NULL to use the default section 5111 . v - The local vector 5112 . point - The point in the DM 5113 . values - The array of values 5114 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 5115 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 5116 5117 Fortran Notes: 5118 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5119 5120 Level: intermediate 5121 5122 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 5123 @*/ 5124 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 5125 { 5126 PetscSection clSection; 5127 IS clPoints; 5128 PetscScalar *array; 5129 PetscInt *points = NULL; 5130 const PetscInt *clp, *clperm; 5131 PetscInt depth, numFields, numPoints, p; 5132 PetscErrorCode ierr; 5133 5134 PetscFunctionBeginHot; 5135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5136 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5137 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5138 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5139 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5140 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5141 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 5142 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 5143 PetscFunctionReturn(0); 5144 } 5145 /* Get points */ 5146 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 5147 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5148 /* Get array */ 5149 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5150 /* Get values */ 5151 if (numFields > 0) { 5152 PetscInt offset = 0, f; 5153 for (f = 0; f < numFields; ++f) { 5154 const PetscInt **perms = NULL; 5155 const PetscScalar **flips = NULL; 5156 5157 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5158 switch (mode) { 5159 case INSERT_VALUES: 5160 for (p = 0; p < numPoints; p++) { 5161 const PetscInt point = points[2*p]; 5162 const PetscInt *perm = perms ? perms[p] : NULL; 5163 const PetscScalar *flip = flips ? flips[p] : NULL; 5164 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 5165 } break; 5166 case INSERT_ALL_VALUES: 5167 for (p = 0; p < numPoints; p++) { 5168 const PetscInt point = points[2*p]; 5169 const PetscInt *perm = perms ? perms[p] : NULL; 5170 const PetscScalar *flip = flips ? flips[p] : NULL; 5171 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 5172 } break; 5173 case INSERT_BC_VALUES: 5174 for (p = 0; p < numPoints; p++) { 5175 const PetscInt point = points[2*p]; 5176 const PetscInt *perm = perms ? perms[p] : NULL; 5177 const PetscScalar *flip = flips ? flips[p] : NULL; 5178 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 5179 } break; 5180 case ADD_VALUES: 5181 for (p = 0; p < numPoints; p++) { 5182 const PetscInt point = points[2*p]; 5183 const PetscInt *perm = perms ? perms[p] : NULL; 5184 const PetscScalar *flip = flips ? flips[p] : NULL; 5185 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 5186 } break; 5187 case ADD_ALL_VALUES: 5188 for (p = 0; p < numPoints; p++) { 5189 const PetscInt point = points[2*p]; 5190 const PetscInt *perm = perms ? perms[p] : NULL; 5191 const PetscScalar *flip = flips ? flips[p] : NULL; 5192 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 5193 } break; 5194 case ADD_BC_VALUES: 5195 for (p = 0; p < numPoints; p++) { 5196 const PetscInt point = points[2*p]; 5197 const PetscInt *perm = perms ? perms[p] : NULL; 5198 const PetscScalar *flip = flips ? flips[p] : NULL; 5199 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 5200 } break; 5201 default: 5202 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5203 } 5204 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5205 } 5206 } else { 5207 PetscInt dof, off; 5208 const PetscInt **perms = NULL; 5209 const PetscScalar **flips = NULL; 5210 5211 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5212 switch (mode) { 5213 case INSERT_VALUES: 5214 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5215 const PetscInt point = points[2*p]; 5216 const PetscInt *perm = perms ? perms[p] : NULL; 5217 const PetscScalar *flip = flips ? flips[p] : NULL; 5218 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5219 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 5220 } break; 5221 case INSERT_ALL_VALUES: 5222 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5223 const PetscInt point = points[2*p]; 5224 const PetscInt *perm = perms ? perms[p] : NULL; 5225 const PetscScalar *flip = flips ? flips[p] : NULL; 5226 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5227 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 5228 } break; 5229 case INSERT_BC_VALUES: 5230 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5231 const PetscInt point = points[2*p]; 5232 const PetscInt *perm = perms ? perms[p] : NULL; 5233 const PetscScalar *flip = flips ? flips[p] : NULL; 5234 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5235 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 5236 } break; 5237 case ADD_VALUES: 5238 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5239 const PetscInt point = points[2*p]; 5240 const PetscInt *perm = perms ? perms[p] : NULL; 5241 const PetscScalar *flip = flips ? flips[p] : NULL; 5242 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5243 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 5244 } break; 5245 case ADD_ALL_VALUES: 5246 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5247 const PetscInt point = points[2*p]; 5248 const PetscInt *perm = perms ? perms[p] : NULL; 5249 const PetscScalar *flip = flips ? flips[p] : NULL; 5250 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5251 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 5252 } break; 5253 case ADD_BC_VALUES: 5254 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5255 const PetscInt point = points[2*p]; 5256 const PetscInt *perm = perms ? perms[p] : NULL; 5257 const PetscScalar *flip = flips ? flips[p] : NULL; 5258 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5259 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 5260 } break; 5261 default: 5262 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5263 } 5264 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5265 } 5266 /* Cleanup points */ 5267 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5268 /* Cleanup array */ 5269 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5270 PetscFunctionReturn(0); 5271 } 5272 5273 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 5274 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], const PetscScalar values[], InsertMode mode) 5275 { 5276 PetscSection clSection; 5277 IS clPoints; 5278 PetscScalar *array; 5279 PetscInt *points = NULL; 5280 const PetscInt *clp; 5281 PetscInt numFields, numPoints, p; 5282 PetscInt offset = 0, f; 5283 PetscErrorCode ierr; 5284 5285 PetscFunctionBeginHot; 5286 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5287 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5288 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5289 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5290 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5291 /* Get points */ 5292 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5293 /* Get array */ 5294 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5295 /* Get values */ 5296 for (f = 0; f < numFields; ++f) { 5297 const PetscInt **perms = NULL; 5298 const PetscScalar **flips = NULL; 5299 5300 if (!fieldActive[f]) { 5301 for (p = 0; p < numPoints*2; p += 2) { 5302 PetscInt fdof; 5303 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5304 offset += fdof; 5305 } 5306 continue; 5307 } 5308 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5309 switch (mode) { 5310 case INSERT_VALUES: 5311 for (p = 0; p < numPoints; p++) { 5312 const PetscInt point = points[2*p]; 5313 const PetscInt *perm = perms ? perms[p] : NULL; 5314 const PetscScalar *flip = flips ? flips[p] : NULL; 5315 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 5316 } break; 5317 case INSERT_ALL_VALUES: 5318 for (p = 0; p < numPoints; p++) { 5319 const PetscInt point = points[2*p]; 5320 const PetscInt *perm = perms ? perms[p] : NULL; 5321 const PetscScalar *flip = flips ? flips[p] : NULL; 5322 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 5323 } break; 5324 case INSERT_BC_VALUES: 5325 for (p = 0; p < numPoints; p++) { 5326 const PetscInt point = points[2*p]; 5327 const PetscInt *perm = perms ? perms[p] : NULL; 5328 const PetscScalar *flip = flips ? flips[p] : NULL; 5329 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 5330 } break; 5331 case ADD_VALUES: 5332 for (p = 0; p < numPoints; p++) { 5333 const PetscInt point = points[2*p]; 5334 const PetscInt *perm = perms ? perms[p] : NULL; 5335 const PetscScalar *flip = flips ? flips[p] : NULL; 5336 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 5337 } break; 5338 case ADD_ALL_VALUES: 5339 for (p = 0; p < numPoints; p++) { 5340 const PetscInt point = points[2*p]; 5341 const PetscInt *perm = perms ? perms[p] : NULL; 5342 const PetscScalar *flip = flips ? flips[p] : NULL; 5343 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 5344 } break; 5345 default: 5346 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5347 } 5348 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5349 } 5350 /* Cleanup points */ 5351 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5352 /* Cleanup array */ 5353 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5354 PetscFunctionReturn(0); 5355 } 5356 5357 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 5358 { 5359 PetscMPIInt rank; 5360 PetscInt i, j; 5361 PetscErrorCode ierr; 5362 5363 PetscFunctionBegin; 5364 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 5365 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 5366 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 5367 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 5368 numCIndices = numCIndices ? numCIndices : numRIndices; 5369 for (i = 0; i < numRIndices; i++) { 5370 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 5371 for (j = 0; j < numCIndices; j++) { 5372 #if defined(PETSC_USE_COMPLEX) 5373 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 5374 #else 5375 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 5376 #endif 5377 } 5378 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 5379 } 5380 PetscFunctionReturn(0); 5381 } 5382 5383 /* 5384 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 5385 5386 Input Parameters: 5387 + section - The section for this data layout 5388 . islocal - Is the section (and thus indices being requested) local or global? 5389 . point - The point contributing dofs with these indices 5390 . off - The global offset of this point 5391 . loff - The local offset of each field 5392 . setBC - The flag determining whether to include indices of bounsary values 5393 . perm - A permutation of the dofs on this point, or NULL 5394 - indperm - A permutation of the entire indices array, or NULL 5395 5396 Output Parameter: 5397 . indices - Indices for dofs on this point 5398 5399 Level: developer 5400 5401 Note: The indices could be local or global, depending on the value of 'off'. 5402 */ 5403 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 5404 { 5405 PetscInt dof; /* The number of unknowns on this point */ 5406 PetscInt cdof; /* The number of constraints on this point */ 5407 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5408 PetscInt cind = 0, k; 5409 PetscErrorCode ierr; 5410 5411 PetscFunctionBegin; 5412 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 5413 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5414 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5415 if (!cdof || setBC) { 5416 for (k = 0; k < dof; ++k) { 5417 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 5418 const PetscInt ind = indperm ? indperm[preind] : preind; 5419 5420 indices[ind] = off + k; 5421 } 5422 } else { 5423 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5424 for (k = 0; k < dof; ++k) { 5425 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 5426 const PetscInt ind = indperm ? indperm[preind] : preind; 5427 5428 if ((cind < cdof) && (k == cdofs[cind])) { 5429 /* Insert check for returning constrained indices */ 5430 indices[ind] = -(off+k+1); 5431 ++cind; 5432 } else { 5433 indices[ind] = off + k - (islocal ? 0 : cind); 5434 } 5435 } 5436 } 5437 *loff += dof; 5438 PetscFunctionReturn(0); 5439 } 5440 5441 /* 5442 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 5443 5444 Input Parameters: 5445 + section - a section (global or local) 5446 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 5447 . point - point within section 5448 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 5449 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 5450 . setBC - identify constrained (boundary condition) points via involution. 5451 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 5452 . permsoff - offset 5453 - indperm - index permutation 5454 5455 Output Parameter: 5456 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 5457 . indices - array to hold indices (as defined by section) of each dof associated with point 5458 5459 Notes: 5460 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 5461 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 5462 in the local vector. 5463 5464 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 5465 significant). It is invalid to call with a global section and setBC=true. 5466 5467 Developer Note: 5468 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 5469 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 5470 offset could be obtained from the section instead of passing it explicitly as we do now. 5471 5472 Example: 5473 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 5474 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 5475 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 5476 The global vector does not store constrained dofs, so when this function returns global indices, say {110, -112, 111}, the value of -112 is an arbitrary flag that should not be interpreted beyond its sign. 5477 5478 Level: developer 5479 */ 5480 PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 5481 { 5482 PetscInt numFields, foff, f; 5483 PetscErrorCode ierr; 5484 5485 PetscFunctionBegin; 5486 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 5487 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5488 for (f = 0, foff = 0; f < numFields; ++f) { 5489 PetscInt fdof, cfdof; 5490 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5491 PetscInt cind = 0, b; 5492 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 5493 5494 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5495 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 5496 if (!cfdof || setBC) { 5497 for (b = 0; b < fdof; ++b) { 5498 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 5499 const PetscInt ind = indperm ? indperm[preind] : preind; 5500 5501 indices[ind] = off+foff+b; 5502 } 5503 } else { 5504 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5505 for (b = 0; b < fdof; ++b) { 5506 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 5507 const PetscInt ind = indperm ? indperm[preind] : preind; 5508 5509 if ((cind < cfdof) && (b == fcdofs[cind])) { 5510 indices[ind] = -(off+foff+b+1); 5511 ++cind; 5512 } else { 5513 indices[ind] = off + foff + b - (islocal ? 0 : cind); 5514 } 5515 } 5516 } 5517 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 5518 foffs[f] += fdof; 5519 } 5520 PetscFunctionReturn(0); 5521 } 5522 5523 /* 5524 This version believes the globalSection offsets for each field, rather than just the point offset 5525 5526 . foffs - The offset into 'indices' for each field, since it is segregated by field 5527 5528 Notes: 5529 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 5530 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 5531 */ 5532 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 5533 { 5534 PetscInt numFields, foff, f; 5535 PetscErrorCode ierr; 5536 5537 PetscFunctionBegin; 5538 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5539 for (f = 0; f < numFields; ++f) { 5540 PetscInt fdof, cfdof; 5541 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5542 PetscInt cind = 0, b; 5543 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 5544 5545 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5546 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 5547 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 5548 if (!cfdof) { 5549 for (b = 0; b < fdof; ++b) { 5550 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 5551 const PetscInt ind = indperm ? indperm[preind] : preind; 5552 5553 indices[ind] = foff+b; 5554 } 5555 } else { 5556 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5557 for (b = 0; b < fdof; ++b) { 5558 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 5559 const PetscInt ind = indperm ? indperm[preind] : preind; 5560 5561 if ((cind < cfdof) && (b == fcdofs[cind])) { 5562 indices[ind] = -(foff+b+1); 5563 ++cind; 5564 } else { 5565 indices[ind] = foff+b-cind; 5566 } 5567 } 5568 } 5569 foffs[f] += fdof; 5570 } 5571 PetscFunctionReturn(0); 5572 } 5573 5574 PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft) 5575 { 5576 Mat cMat; 5577 PetscSection aSec, cSec; 5578 IS aIS; 5579 PetscInt aStart = -1, aEnd = -1; 5580 const PetscInt *anchors; 5581 PetscInt numFields, f, p, q, newP = 0; 5582 PetscInt newNumPoints = 0, newNumIndices = 0; 5583 PetscInt *newPoints, *indices, *newIndices; 5584 PetscInt maxAnchor, maxDof; 5585 PetscInt newOffsets[32]; 5586 PetscInt *pointMatOffsets[32]; 5587 PetscInt *newPointOffsets[32]; 5588 PetscScalar *pointMat[32]; 5589 PetscScalar *newValues=NULL,*tmpValues; 5590 PetscBool anyConstrained = PETSC_FALSE; 5591 PetscErrorCode ierr; 5592 5593 PetscFunctionBegin; 5594 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5595 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5596 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5597 5598 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 5599 /* if there are point-to-point constraints */ 5600 if (aSec) { 5601 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 5602 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 5603 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 5604 /* figure out how many points are going to be in the new element matrix 5605 * (we allow double counting, because it's all just going to be summed 5606 * into the global matrix anyway) */ 5607 for (p = 0; p < 2*numPoints; p+=2) { 5608 PetscInt b = points[p]; 5609 PetscInt bDof = 0, bSecDof; 5610 5611 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5612 if (!bSecDof) { 5613 continue; 5614 } 5615 if (b >= aStart && b < aEnd) { 5616 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 5617 } 5618 if (bDof) { 5619 /* this point is constrained */ 5620 /* it is going to be replaced by its anchors */ 5621 PetscInt bOff, q; 5622 5623 anyConstrained = PETSC_TRUE; 5624 newNumPoints += bDof; 5625 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 5626 for (q = 0; q < bDof; q++) { 5627 PetscInt a = anchors[bOff + q]; 5628 PetscInt aDof; 5629 5630 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 5631 newNumIndices += aDof; 5632 for (f = 0; f < numFields; ++f) { 5633 PetscInt fDof; 5634 5635 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 5636 newOffsets[f+1] += fDof; 5637 } 5638 } 5639 } 5640 else { 5641 /* this point is not constrained */ 5642 newNumPoints++; 5643 newNumIndices += bSecDof; 5644 for (f = 0; f < numFields; ++f) { 5645 PetscInt fDof; 5646 5647 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5648 newOffsets[f+1] += fDof; 5649 } 5650 } 5651 } 5652 } 5653 if (!anyConstrained) { 5654 if (outNumPoints) *outNumPoints = 0; 5655 if (outNumIndices) *outNumIndices = 0; 5656 if (outPoints) *outPoints = NULL; 5657 if (outValues) *outValues = NULL; 5658 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5659 PetscFunctionReturn(0); 5660 } 5661 5662 if (outNumPoints) *outNumPoints = newNumPoints; 5663 if (outNumIndices) *outNumIndices = newNumIndices; 5664 5665 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 5666 5667 if (!outPoints && !outValues) { 5668 if (offsets) { 5669 for (f = 0; f <= numFields; f++) { 5670 offsets[f] = newOffsets[f]; 5671 } 5672 } 5673 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5674 PetscFunctionReturn(0); 5675 } 5676 5677 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 5678 5679 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 5680 5681 /* workspaces */ 5682 if (numFields) { 5683 for (f = 0; f < numFields; f++) { 5684 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5685 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5686 } 5687 } 5688 else { 5689 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5690 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5691 } 5692 5693 /* get workspaces for the point-to-point matrices */ 5694 if (numFields) { 5695 PetscInt totalOffset, totalMatOffset; 5696 5697 for (p = 0; p < numPoints; p++) { 5698 PetscInt b = points[2*p]; 5699 PetscInt bDof = 0, bSecDof; 5700 5701 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5702 if (!bSecDof) { 5703 for (f = 0; f < numFields; f++) { 5704 newPointOffsets[f][p + 1] = 0; 5705 pointMatOffsets[f][p + 1] = 0; 5706 } 5707 continue; 5708 } 5709 if (b >= aStart && b < aEnd) { 5710 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5711 } 5712 if (bDof) { 5713 for (f = 0; f < numFields; f++) { 5714 PetscInt fDof, q, bOff, allFDof = 0; 5715 5716 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5717 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5718 for (q = 0; q < bDof; q++) { 5719 PetscInt a = anchors[bOff + q]; 5720 PetscInt aFDof; 5721 5722 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 5723 allFDof += aFDof; 5724 } 5725 newPointOffsets[f][p+1] = allFDof; 5726 pointMatOffsets[f][p+1] = fDof * allFDof; 5727 } 5728 } 5729 else { 5730 for (f = 0; f < numFields; f++) { 5731 PetscInt fDof; 5732 5733 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5734 newPointOffsets[f][p+1] = fDof; 5735 pointMatOffsets[f][p+1] = 0; 5736 } 5737 } 5738 } 5739 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 5740 newPointOffsets[f][0] = totalOffset; 5741 pointMatOffsets[f][0] = totalMatOffset; 5742 for (p = 0; p < numPoints; p++) { 5743 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 5744 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 5745 } 5746 totalOffset = newPointOffsets[f][numPoints]; 5747 totalMatOffset = pointMatOffsets[f][numPoints]; 5748 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5749 } 5750 } 5751 else { 5752 for (p = 0; p < numPoints; p++) { 5753 PetscInt b = points[2*p]; 5754 PetscInt bDof = 0, bSecDof; 5755 5756 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5757 if (!bSecDof) { 5758 newPointOffsets[0][p + 1] = 0; 5759 pointMatOffsets[0][p + 1] = 0; 5760 continue; 5761 } 5762 if (b >= aStart && b < aEnd) { 5763 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5764 } 5765 if (bDof) { 5766 PetscInt bOff, q, allDof = 0; 5767 5768 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5769 for (q = 0; q < bDof; q++) { 5770 PetscInt a = anchors[bOff + q], aDof; 5771 5772 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 5773 allDof += aDof; 5774 } 5775 newPointOffsets[0][p+1] = allDof; 5776 pointMatOffsets[0][p+1] = bSecDof * allDof; 5777 } 5778 else { 5779 newPointOffsets[0][p+1] = bSecDof; 5780 pointMatOffsets[0][p+1] = 0; 5781 } 5782 } 5783 newPointOffsets[0][0] = 0; 5784 pointMatOffsets[0][0] = 0; 5785 for (p = 0; p < numPoints; p++) { 5786 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 5787 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 5788 } 5789 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5790 } 5791 5792 /* output arrays */ 5793 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5794 5795 /* get the point-to-point matrices; construct newPoints */ 5796 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 5797 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 5798 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5799 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5800 if (numFields) { 5801 for (p = 0, newP = 0; p < numPoints; p++) { 5802 PetscInt b = points[2*p]; 5803 PetscInt o = points[2*p+1]; 5804 PetscInt bDof = 0, bSecDof; 5805 5806 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5807 if (!bSecDof) { 5808 continue; 5809 } 5810 if (b >= aStart && b < aEnd) { 5811 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5812 } 5813 if (bDof) { 5814 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 5815 5816 fStart[0] = 0; 5817 fEnd[0] = 0; 5818 for (f = 0; f < numFields; f++) { 5819 PetscInt fDof; 5820 5821 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 5822 fStart[f+1] = fStart[f] + fDof; 5823 fEnd[f+1] = fStart[f+1]; 5824 } 5825 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5826 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 5827 5828 fAnchorStart[0] = 0; 5829 fAnchorEnd[0] = 0; 5830 for (f = 0; f < numFields; f++) { 5831 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 5832 5833 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 5834 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 5835 } 5836 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5837 for (q = 0; q < bDof; q++) { 5838 PetscInt a = anchors[bOff + q], aOff; 5839 5840 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5841 newPoints[2*(newP + q)] = a; 5842 newPoints[2*(newP + q) + 1] = 0; 5843 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5844 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 5845 } 5846 newP += bDof; 5847 5848 if (outValues) { 5849 /* get the point-to-point submatrix */ 5850 for (f = 0; f < numFields; f++) { 5851 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 5852 } 5853 } 5854 } 5855 else { 5856 newPoints[2 * newP] = b; 5857 newPoints[2 * newP + 1] = o; 5858 newP++; 5859 } 5860 } 5861 } else { 5862 for (p = 0; p < numPoints; p++) { 5863 PetscInt b = points[2*p]; 5864 PetscInt o = points[2*p+1]; 5865 PetscInt bDof = 0, bSecDof; 5866 5867 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5868 if (!bSecDof) { 5869 continue; 5870 } 5871 if (b >= aStart && b < aEnd) { 5872 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5873 } 5874 if (bDof) { 5875 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 5876 5877 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5878 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 5879 5880 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 5881 for (q = 0; q < bDof; q++) { 5882 PetscInt a = anchors[bOff + q], aOff; 5883 5884 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5885 5886 newPoints[2*(newP + q)] = a; 5887 newPoints[2*(newP + q) + 1] = 0; 5888 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5889 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 5890 } 5891 newP += bDof; 5892 5893 /* get the point-to-point submatrix */ 5894 if (outValues) { 5895 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 5896 } 5897 } 5898 else { 5899 newPoints[2 * newP] = b; 5900 newPoints[2 * newP + 1] = o; 5901 newP++; 5902 } 5903 } 5904 } 5905 5906 if (outValues) { 5907 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5908 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 5909 /* multiply constraints on the right */ 5910 if (numFields) { 5911 for (f = 0; f < numFields; f++) { 5912 PetscInt oldOff = offsets[f]; 5913 5914 for (p = 0; p < numPoints; p++) { 5915 PetscInt cStart = newPointOffsets[f][p]; 5916 PetscInt b = points[2 * p]; 5917 PetscInt c, r, k; 5918 PetscInt dof; 5919 5920 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5921 if (!dof) { 5922 continue; 5923 } 5924 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5925 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 5926 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 5927 5928 for (r = 0; r < numIndices; r++) { 5929 for (c = 0; c < nCols; c++) { 5930 for (k = 0; k < dof; k++) { 5931 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 5932 } 5933 } 5934 } 5935 } 5936 else { 5937 /* copy this column as is */ 5938 for (r = 0; r < numIndices; r++) { 5939 for (c = 0; c < dof; c++) { 5940 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5941 } 5942 } 5943 } 5944 oldOff += dof; 5945 } 5946 } 5947 } 5948 else { 5949 PetscInt oldOff = 0; 5950 for (p = 0; p < numPoints; p++) { 5951 PetscInt cStart = newPointOffsets[0][p]; 5952 PetscInt b = points[2 * p]; 5953 PetscInt c, r, k; 5954 PetscInt dof; 5955 5956 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5957 if (!dof) { 5958 continue; 5959 } 5960 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5961 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 5962 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 5963 5964 for (r = 0; r < numIndices; r++) { 5965 for (c = 0; c < nCols; c++) { 5966 for (k = 0; k < dof; k++) { 5967 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 5968 } 5969 } 5970 } 5971 } 5972 else { 5973 /* copy this column as is */ 5974 for (r = 0; r < numIndices; r++) { 5975 for (c = 0; c < dof; c++) { 5976 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5977 } 5978 } 5979 } 5980 oldOff += dof; 5981 } 5982 } 5983 5984 if (multiplyLeft) { 5985 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5986 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 5987 /* multiply constraints transpose on the left */ 5988 if (numFields) { 5989 for (f = 0; f < numFields; f++) { 5990 PetscInt oldOff = offsets[f]; 5991 5992 for (p = 0; p < numPoints; p++) { 5993 PetscInt rStart = newPointOffsets[f][p]; 5994 PetscInt b = points[2 * p]; 5995 PetscInt c, r, k; 5996 PetscInt dof; 5997 5998 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5999 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6000 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 6001 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 6002 6003 for (r = 0; r < nRows; r++) { 6004 for (c = 0; c < newNumIndices; c++) { 6005 for (k = 0; k < dof; k++) { 6006 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6007 } 6008 } 6009 } 6010 } 6011 else { 6012 /* copy this row as is */ 6013 for (r = 0; r < dof; r++) { 6014 for (c = 0; c < newNumIndices; c++) { 6015 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 6016 } 6017 } 6018 } 6019 oldOff += dof; 6020 } 6021 } 6022 } 6023 else { 6024 PetscInt oldOff = 0; 6025 6026 for (p = 0; p < numPoints; p++) { 6027 PetscInt rStart = newPointOffsets[0][p]; 6028 PetscInt b = points[2 * p]; 6029 PetscInt c, r, k; 6030 PetscInt dof; 6031 6032 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 6033 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6034 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 6035 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 6036 6037 for (r = 0; r < nRows; r++) { 6038 for (c = 0; c < newNumIndices; c++) { 6039 for (k = 0; k < dof; k++) { 6040 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6041 } 6042 } 6043 } 6044 } 6045 else { 6046 /* copy this row as is */ 6047 for (r = 0; r < dof; r++) { 6048 for (c = 0; c < newNumIndices; c++) { 6049 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 6050 } 6051 } 6052 } 6053 oldOff += dof; 6054 } 6055 } 6056 6057 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 6058 } 6059 else { 6060 newValues = tmpValues; 6061 } 6062 } 6063 6064 /* clean up */ 6065 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6066 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6067 6068 if (numFields) { 6069 for (f = 0; f < numFields; f++) { 6070 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6071 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6072 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6073 } 6074 } 6075 else { 6076 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6077 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6078 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6079 } 6080 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 6081 6082 /* output */ 6083 if (outPoints) { 6084 *outPoints = newPoints; 6085 } 6086 else { 6087 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6088 } 6089 if (outValues) { 6090 *outValues = newValues; 6091 } 6092 for (f = 0; f <= numFields; f++) { 6093 offsets[f] = newOffsets[f]; 6094 } 6095 PetscFunctionReturn(0); 6096 } 6097 6098 /*@C 6099 DMPlexGetClosureIndices - Get the global indices for all local points in the closure of the given point 6100 6101 Not collective 6102 6103 Input Parameters: 6104 + dm - The DM 6105 . section - The section describing the points (a local section) 6106 . idxSection - The section on which to obtain indices (may be local or global) 6107 - point - The mesh point 6108 6109 Output parameters: 6110 + numIndices - The number of indices 6111 . indices - The indices 6112 - outOffsets - Field offset if not NULL 6113 6114 Notes: 6115 Must call DMPlexRestoreClosureIndices() to free allocated memory 6116 6117 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 6118 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 6119 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 6120 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 6121 indices (with the above semantics) are implied. 6122 6123 Level: advanced 6124 6125 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 6126 @*/ 6127 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 6128 { 6129 PetscBool isLocal = (PetscBool)(section == idxSection); 6130 PetscSection clSection; 6131 IS clPoints; 6132 const PetscInt *clp, *clperm; 6133 const PetscInt **perms[32] = {NULL}; 6134 PetscInt *points = NULL, *pointsNew; 6135 PetscInt numPoints, numPointsNew; 6136 PetscInt offsets[32]; 6137 PetscInt Nf, Nind, NindNew, off, idxOff, f, p; 6138 PetscErrorCode ierr; 6139 6140 PetscFunctionBegin; 6141 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6142 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6143 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 6144 if (numIndices) PetscValidPointer(numIndices, 4); 6145 PetscValidPointer(indices, 5); 6146 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 6147 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 6148 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 6149 /* Get points in closure */ 6150 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6151 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 6152 /* Get number of indices and indices per field */ 6153 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 6154 PetscInt dof, fdof; 6155 6156 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6157 for (f = 0; f < Nf; ++f) { 6158 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6159 offsets[f+1] += fdof; 6160 } 6161 Nind += dof; 6162 } 6163 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 6164 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Nind); 6165 if (!Nf) offsets[1] = Nind; 6166 /* Get dual space symmetries */ 6167 for (f = 0; f < PetscMax(1,Nf); f++) { 6168 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 6169 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 6170 } 6171 /* Correct for hanging node constraints */ 6172 { 6173 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, perms, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 6174 if (numPointsNew) { 6175 for (f = 0; f < PetscMax(1,Nf); f++) { 6176 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 6177 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 6178 } 6179 for (f = 0; f < PetscMax(1,Nf); f++) { 6180 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 6181 else {ierr = PetscSectionGetPointSyms(section,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 6182 } 6183 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6184 numPoints = numPointsNew; 6185 Nind = NindNew; 6186 points = pointsNew; 6187 } 6188 } 6189 /* Calculate indices */ 6190 ierr = DMGetWorkArray(dm, Nind, MPIU_INT, indices);CHKERRQ(ierr); 6191 if (Nf) { 6192 if (outOffsets) { 6193 PetscInt f; 6194 6195 for (f = 0; f <= Nf; f++) { 6196 outOffsets[f] = offsets[f]; 6197 } 6198 } 6199 for (p = 0; p < numPoints; p++) { 6200 ierr = PetscSectionGetOffset(idxSection, points[2*p], &idxOff);CHKERRQ(ierr); 6201 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, points[2*p], idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, *indices);CHKERRQ(ierr); 6202 } 6203 } else { 6204 for (p = 0, off = 0; p < numPoints; p++) { 6205 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 6206 6207 ierr = PetscSectionGetOffset(idxSection, points[2*p], &idxOff);CHKERRQ(ierr); 6208 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, points[2*p], idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, *indices);CHKERRQ(ierr); 6209 } 6210 } 6211 /* Cleanup points */ 6212 for (f = 0; f < PetscMax(1,Nf); f++) { 6213 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 6214 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 6215 } 6216 if (numPointsNew) { 6217 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, MPIU_INT, &pointsNew);CHKERRQ(ierr); 6218 } else { 6219 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6220 } 6221 if (numIndices) *numIndices = Nind; 6222 PetscFunctionReturn(0); 6223 } 6224 6225 /*@C 6226 DMPlexRestoreClosureIndices - Restore the indices in a vector v for all points in the closure of the given point 6227 6228 Not collective 6229 6230 Input Parameters: 6231 + dm - The DM 6232 . section - The section describing the layout in v, or NULL to use the default section 6233 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 6234 . point - The mesh point 6235 . numIndices - The number of indices 6236 . indices - The indices 6237 - outOffsets - Field offset if not NULL 6238 6239 Level: advanced 6240 6241 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 6242 @*/ 6243 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 6244 { 6245 PetscErrorCode ierr; 6246 6247 PetscFunctionBegin; 6248 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6249 PetscValidPointer(indices, 5); 6250 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 6251 PetscFunctionReturn(0); 6252 } 6253 6254 /*@C 6255 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 6256 6257 Not collective 6258 6259 Input Parameters: 6260 + dm - The DM 6261 . section - The section describing the layout in v, or NULL to use the default section 6262 . globalSection - The section describing the layout in v, or NULL to use the default global section 6263 . A - The matrix 6264 . point - The point in the DM 6265 . values - The array of values 6266 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6267 6268 Fortran Notes: 6269 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6270 6271 Level: intermediate 6272 6273 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 6274 @*/ 6275 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6276 { 6277 DM_Plex *mesh = (DM_Plex*) dm->data; 6278 PetscSection clSection; 6279 IS clPoints; 6280 PetscInt *points = NULL, *newPoints; 6281 const PetscInt *clp, *clperm; 6282 PetscInt *indices; 6283 PetscInt offsets[32]; 6284 const PetscInt **perms[32] = {NULL}; 6285 const PetscScalar **flips[32] = {NULL}; 6286 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, p, f; 6287 PetscScalar *valCopy = NULL; 6288 PetscScalar *newValues; 6289 PetscErrorCode ierr; 6290 6291 PetscFunctionBegin; 6292 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6293 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6294 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6295 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 6296 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 6297 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 6298 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6299 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6300 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 6301 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 6302 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6303 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 6304 PetscInt fdof; 6305 6306 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6307 for (f = 0; f < numFields; ++f) { 6308 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6309 offsets[f+1] += fdof; 6310 } 6311 numIndices += dof; 6312 } 6313 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 6314 6315 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[numFields], numIndices); 6316 /* Get symmetries */ 6317 for (f = 0; f < PetscMax(1,numFields); f++) { 6318 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 6319 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 6320 if (values && flips[f]) { /* may need to apply sign changes to the element matrix */ 6321 PetscInt foffset = offsets[f]; 6322 6323 for (p = 0; p < numPoints; p++) { 6324 PetscInt point = points[2*p], fdof; 6325 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 6326 6327 if (!numFields) { 6328 ierr = PetscSectionGetDof(section,point,&fdof);CHKERRQ(ierr); 6329 } else { 6330 ierr = PetscSectionGetFieldDof(section,point,f,&fdof);CHKERRQ(ierr); 6331 } 6332 if (flip) { 6333 PetscInt i, j, k; 6334 6335 if (!valCopy) { 6336 ierr = DMGetWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 6337 for (j = 0; j < numIndices * numIndices; j++) valCopy[j] = values[j]; 6338 values = valCopy; 6339 } 6340 for (i = 0; i < fdof; i++) { 6341 PetscScalar fval = flip[i]; 6342 6343 for (k = 0; k < numIndices; k++) { 6344 valCopy[numIndices * (foffset + i) + k] *= fval; 6345 valCopy[numIndices * k + (foffset + i)] *= fval; 6346 } 6347 } 6348 } 6349 foffset += fdof; 6350 } 6351 } 6352 } 6353 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,perms,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 6354 if (newNumPoints) { 6355 if (valCopy) { 6356 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 6357 } 6358 for (f = 0; f < PetscMax(1,numFields); f++) { 6359 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 6360 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 6361 } 6362 for (f = 0; f < PetscMax(1,numFields); f++) { 6363 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 6364 else {ierr = PetscSectionGetPointSyms(section,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 6365 } 6366 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6367 numPoints = newNumPoints; 6368 numIndices = newNumIndices; 6369 points = newPoints; 6370 values = newValues; 6371 } 6372 ierr = DMGetWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 6373 if (numFields) { 6374 PetscBool useFieldOffsets; 6375 6376 ierr = PetscSectionGetUseFieldOffsets(globalSection, &useFieldOffsets);CHKERRQ(ierr); 6377 if (useFieldOffsets) { 6378 for (p = 0; p < numPoints; p++) { 6379 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, globalSection, points[2*p], offsets, perms, p, clperm, indices);CHKERRQ(ierr); 6380 } 6381 } else { 6382 for (p = 0; p < numPoints; p++) { 6383 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 6384 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 6385 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 6386 * global section. */ 6387 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_FALSE, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, clperm, indices);CHKERRQ(ierr); 6388 } 6389 } 6390 } else { 6391 for (p = 0, off = 0; p < numPoints; p++) { 6392 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 6393 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 6394 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 6395 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 6396 * global section. */ 6397 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_FALSE, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, clperm, indices);CHKERRQ(ierr); 6398 } 6399 } 6400 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 6401 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);CHKERRQ(ierr); 6402 if (mesh->printFEM > 1) { 6403 PetscInt i; 6404 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 6405 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 6406 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6407 } 6408 if (ierr) { 6409 PetscMPIInt rank; 6410 PetscErrorCode ierr2; 6411 6412 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 6413 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 6414 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 6415 ierr2 = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr2); 6416 CHKERRQ(ierr); 6417 } 6418 for (f = 0; f < PetscMax(1,numFields); f++) { 6419 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 6420 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 6421 } 6422 if (newNumPoints) { 6423 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 6424 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6425 } 6426 else { 6427 if (valCopy) { 6428 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 6429 } 6430 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6431 } 6432 ierr = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 6433 PetscFunctionReturn(0); 6434 } 6435 6436 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6437 { 6438 DM_Plex *mesh = (DM_Plex*) dmf->data; 6439 PetscInt *fpoints = NULL, *ftotpoints = NULL; 6440 PetscInt *cpoints = NULL; 6441 PetscInt *findices, *cindices; 6442 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 6443 PetscInt foffsets[32], coffsets[32]; 6444 CellRefiner cellRefiner; 6445 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 6446 PetscErrorCode ierr; 6447 6448 PetscFunctionBegin; 6449 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 6450 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 6451 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 6452 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 6453 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 6454 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 6455 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 6456 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 6457 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 6458 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 6459 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 6460 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 6461 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6462 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 6463 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 6464 /* Column indices */ 6465 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6466 maxFPoints = numCPoints; 6467 /* Compress out points not in the section */ 6468 /* TODO: Squeeze out points with 0 dof as well */ 6469 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 6470 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 6471 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 6472 cpoints[q*2] = cpoints[p]; 6473 cpoints[q*2+1] = cpoints[p+1]; 6474 ++q; 6475 } 6476 } 6477 numCPoints = q; 6478 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 6479 PetscInt fdof; 6480 6481 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 6482 if (!dof) continue; 6483 for (f = 0; f < numFields; ++f) { 6484 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 6485 coffsets[f+1] += fdof; 6486 } 6487 numCIndices += dof; 6488 } 6489 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 6490 /* Row indices */ 6491 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 6492 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 6493 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6494 for (r = 0, q = 0; r < numSubcells; ++r) { 6495 /* TODO Map from coarse to fine cells */ 6496 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6497 /* Compress out points not in the section */ 6498 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 6499 for (p = 0; p < numFPoints*2; p += 2) { 6500 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 6501 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 6502 if (!dof) continue; 6503 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 6504 if (s < q) continue; 6505 ftotpoints[q*2] = fpoints[p]; 6506 ftotpoints[q*2+1] = fpoints[p+1]; 6507 ++q; 6508 } 6509 } 6510 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6511 } 6512 numFPoints = q; 6513 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 6514 PetscInt fdof; 6515 6516 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 6517 if (!dof) continue; 6518 for (f = 0; f < numFields; ++f) { 6519 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 6520 foffsets[f+1] += fdof; 6521 } 6522 numFIndices += dof; 6523 } 6524 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 6525 6526 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 6527 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 6528 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 6529 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 6530 if (numFields) { 6531 const PetscInt **permsF[32] = {NULL}; 6532 const PetscInt **permsC[32] = {NULL}; 6533 6534 for (f = 0; f < numFields; f++) { 6535 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6536 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6537 } 6538 for (p = 0; p < numFPoints; p++) { 6539 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6540 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 6541 } 6542 for (p = 0; p < numCPoints; p++) { 6543 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6544 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 6545 } 6546 for (f = 0; f < numFields; f++) { 6547 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6548 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6549 } 6550 } else { 6551 const PetscInt **permsF = NULL; 6552 const PetscInt **permsC = NULL; 6553 6554 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6555 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6556 for (p = 0, off = 0; p < numFPoints; p++) { 6557 const PetscInt *perm = permsF ? permsF[p] : NULL; 6558 6559 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6560 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 6561 } 6562 for (p = 0, off = 0; p < numCPoints; p++) { 6563 const PetscInt *perm = permsC ? permsC[p] : NULL; 6564 6565 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6566 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 6567 } 6568 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6569 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6570 } 6571 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 6572 /* TODO: flips */ 6573 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 6574 if (ierr) { 6575 PetscMPIInt rank; 6576 PetscErrorCode ierr2; 6577 6578 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 6579 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 6580 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 6581 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 6582 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 6583 CHKERRQ(ierr); 6584 } 6585 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6586 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6587 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 6588 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 6589 PetscFunctionReturn(0); 6590 } 6591 6592 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 6593 { 6594 PetscInt *fpoints = NULL, *ftotpoints = NULL; 6595 PetscInt *cpoints = NULL; 6596 PetscInt foffsets[32], coffsets[32]; 6597 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 6598 CellRefiner cellRefiner; 6599 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 6600 PetscErrorCode ierr; 6601 6602 PetscFunctionBegin; 6603 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 6604 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 6605 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 6606 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 6607 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 6608 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 6609 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 6610 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 6611 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 6612 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 6613 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 6614 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6615 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 6616 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 6617 /* Column indices */ 6618 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6619 maxFPoints = numCPoints; 6620 /* Compress out points not in the section */ 6621 /* TODO: Squeeze out points with 0 dof as well */ 6622 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 6623 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 6624 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 6625 cpoints[q*2] = cpoints[p]; 6626 cpoints[q*2+1] = cpoints[p+1]; 6627 ++q; 6628 } 6629 } 6630 numCPoints = q; 6631 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 6632 PetscInt fdof; 6633 6634 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 6635 if (!dof) continue; 6636 for (f = 0; f < numFields; ++f) { 6637 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 6638 coffsets[f+1] += fdof; 6639 } 6640 numCIndices += dof; 6641 } 6642 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 6643 /* Row indices */ 6644 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 6645 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 6646 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6647 for (r = 0, q = 0; r < numSubcells; ++r) { 6648 /* TODO Map from coarse to fine cells */ 6649 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6650 /* Compress out points not in the section */ 6651 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 6652 for (p = 0; p < numFPoints*2; p += 2) { 6653 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 6654 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 6655 if (!dof) continue; 6656 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 6657 if (s < q) continue; 6658 ftotpoints[q*2] = fpoints[p]; 6659 ftotpoints[q*2+1] = fpoints[p+1]; 6660 ++q; 6661 } 6662 } 6663 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6664 } 6665 numFPoints = q; 6666 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 6667 PetscInt fdof; 6668 6669 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 6670 if (!dof) continue; 6671 for (f = 0; f < numFields; ++f) { 6672 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 6673 foffsets[f+1] += fdof; 6674 } 6675 numFIndices += dof; 6676 } 6677 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 6678 6679 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 6680 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 6681 if (numFields) { 6682 const PetscInt **permsF[32] = {NULL}; 6683 const PetscInt **permsC[32] = {NULL}; 6684 6685 for (f = 0; f < numFields; f++) { 6686 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6687 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6688 } 6689 for (p = 0; p < numFPoints; p++) { 6690 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6691 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 6692 } 6693 for (p = 0; p < numCPoints; p++) { 6694 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6695 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 6696 } 6697 for (f = 0; f < numFields; f++) { 6698 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6699 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6700 } 6701 } else { 6702 const PetscInt **permsF = NULL; 6703 const PetscInt **permsC = NULL; 6704 6705 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6706 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6707 for (p = 0, off = 0; p < numFPoints; p++) { 6708 const PetscInt *perm = permsF ? permsF[p] : NULL; 6709 6710 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6711 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 6712 } 6713 for (p = 0, off = 0; p < numCPoints; p++) { 6714 const PetscInt *perm = permsC ? permsC[p] : NULL; 6715 6716 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6717 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 6718 } 6719 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6720 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6721 } 6722 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6723 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6724 PetscFunctionReturn(0); 6725 } 6726 6727 /*@ 6728 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 6729 6730 Input Parameter: 6731 . dm - The DMPlex object 6732 6733 Output Parameters: 6734 + cMax - The first hybrid cell 6735 . fMax - The first hybrid face 6736 . eMax - The first hybrid edge 6737 - vMax - The first hybrid vertex 6738 6739 Level: developer 6740 6741 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 6742 @*/ 6743 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 6744 { 6745 DM_Plex *mesh = (DM_Plex*) dm->data; 6746 PetscInt dim; 6747 PetscErrorCode ierr; 6748 6749 PetscFunctionBegin; 6750 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6751 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6752 if (dim < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM dimension not yet set"); 6753 if (cMax) *cMax = mesh->hybridPointMax[dim]; 6754 if (fMax) *fMax = mesh->hybridPointMax[PetscMax(dim-1,0)]; 6755 if (eMax) *eMax = mesh->hybridPointMax[1]; 6756 if (vMax) *vMax = mesh->hybridPointMax[0]; 6757 PetscFunctionReturn(0); 6758 } 6759 6760 static PetscErrorCode DMPlexCreateDimStratum(DM dm, DMLabel depthLabel, DMLabel dimLabel, PetscInt d, PetscInt dMax) 6761 { 6762 IS is, his; 6763 PetscInt first = 0, stride; 6764 PetscBool isStride; 6765 PetscErrorCode ierr; 6766 6767 PetscFunctionBegin; 6768 ierr = DMLabelGetStratumIS(depthLabel, d, &is);CHKERRQ(ierr); 6769 ierr = PetscObjectTypeCompare((PetscObject) is, ISSTRIDE, &isStride);CHKERRQ(ierr); 6770 if (isStride) {ierr = ISStrideGetInfo(is, &first, &stride);CHKERRQ(ierr);} 6771 if (is && (!isStride || stride != 1)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM is not stratified: depth %D IS is not contiguous", d); 6772 ierr = ISCreateStride(PETSC_COMM_SELF, (dMax - first), first, 1, &his);CHKERRQ(ierr); 6773 ierr = DMLabelSetStratumIS(dimLabel, d, his);CHKERRQ(ierr); 6774 ierr = ISDestroy(&his);CHKERRQ(ierr); 6775 ierr = ISDestroy(&is);CHKERRQ(ierr); 6776 PetscFunctionReturn(0); 6777 } 6778 6779 /*@ 6780 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 6781 6782 Input Parameters: 6783 + dm - The DMPlex object 6784 . cMax - The first hybrid cell 6785 . fMax - The first hybrid face 6786 . eMax - The first hybrid edge 6787 - vMax - The first hybrid vertex 6788 6789 Level: developer 6790 6791 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 6792 @*/ 6793 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 6794 { 6795 DM_Plex *mesh = (DM_Plex*) dm->data; 6796 PetscInt dim; 6797 PetscErrorCode ierr; 6798 6799 PetscFunctionBegin; 6800 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6801 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6802 if (dim < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM dimension not yet set"); 6803 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 6804 if (fMax >= 0) mesh->hybridPointMax[PetscMax(dim-1,0)] = fMax; 6805 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 6806 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 6807 PetscFunctionReturn(0); 6808 } 6809 6810 /*@C 6811 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 6812 6813 Input Parameter: 6814 . dm - The DMPlex object 6815 6816 Output Parameter: 6817 . cellHeight - The height of a cell 6818 6819 Level: developer 6820 6821 .seealso DMPlexSetVTKCellHeight() 6822 @*/ 6823 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 6824 { 6825 DM_Plex *mesh = (DM_Plex*) dm->data; 6826 6827 PetscFunctionBegin; 6828 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6829 PetscValidPointer(cellHeight, 2); 6830 *cellHeight = mesh->vtkCellHeight; 6831 PetscFunctionReturn(0); 6832 } 6833 6834 /*@C 6835 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 6836 6837 Input Parameters: 6838 + dm - The DMPlex object 6839 - cellHeight - The height of a cell 6840 6841 Level: developer 6842 6843 .seealso DMPlexGetVTKCellHeight() 6844 @*/ 6845 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 6846 { 6847 DM_Plex *mesh = (DM_Plex*) dm->data; 6848 6849 PetscFunctionBegin; 6850 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6851 mesh->vtkCellHeight = cellHeight; 6852 PetscFunctionReturn(0); 6853 } 6854 6855 /*@ 6856 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 6857 6858 Input Parameter: 6859 . dm - The DMPlex object 6860 6861 Output Parameters: 6862 + gcStart - The first ghost cell, or NULL 6863 - gcEnd - The upper bound on ghost cells, or NULL 6864 6865 Level: advanced 6866 6867 .seealso DMPlexConstructGhostCells(), DMPlexSetGhostCellStratum(), DMPlexGetHybridBounds() 6868 @*/ 6869 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 6870 { 6871 DM_Plex *mesh = (DM_Plex*) dm->data; 6872 PetscInt dim; 6873 PetscErrorCode ierr; 6874 6875 PetscFunctionBegin; 6876 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6877 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6878 if (dim < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM dimension not yet set"); 6879 if (gcStart) {PetscValidIntPointer(gcStart, 2); *gcStart = mesh->ghostCellStart;} 6880 if (gcEnd) { 6881 PetscValidIntPointer(gcEnd, 3); 6882 if (mesh->ghostCellStart >= 0) {ierr = DMPlexGetHeightStratum(dm, 0, NULL, gcEnd);CHKERRQ(ierr);} 6883 else {*gcEnd = -1;} 6884 } 6885 PetscFunctionReturn(0); 6886 } 6887 6888 /*@ 6889 DMPlexSetGhostCellStratum - Set the range of cells which are used to enforce FV boundary conditions 6890 6891 Input Parameters: 6892 + dm - The DMPlex object 6893 . gcStart - The first ghost cell, or PETSC_DETERMINE 6894 - gcEnd - The upper bound on ghost cells, or PETSC_DETERMINE 6895 6896 Level: advanced 6897 6898 Note: This is not usually called directly by a user. 6899 6900 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum(), DMPlexSetHybridBounds() 6901 @*/ 6902 PetscErrorCode DMPlexSetGhostCellStratum(DM dm, PetscInt gcStart, PetscInt gcEnd) 6903 { 6904 DM_Plex *mesh = (DM_Plex*) dm->data; 6905 PetscInt dim; 6906 PetscErrorCode ierr; 6907 6908 PetscFunctionBegin; 6909 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6910 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6911 if (dim < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM dimension not yet set"); 6912 mesh->ghostCellStart = gcStart; 6913 if (gcEnd >= 0) { 6914 PetscInt cEnd; 6915 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 6916 if (gcEnd != cEnd) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Ghost cells must appear at the end of the cell range, but gcEnd %D is not equal to cEnd %D", gcEnd, cEnd); 6917 } 6918 PetscFunctionReturn(0); 6919 } 6920 6921 /*@ 6922 DMPlexGetInteriorCellStratum - Get the range of cells which are neither hybrid nor ghost FV cells 6923 6924 Input Parameter: 6925 . dm - The DMPlex object 6926 6927 Output Parameters: 6928 + cStartInterior - The first ghost cell 6929 - cEndInterior - The upper bound on ghost cells 6930 6931 Level: developer 6932 6933 .seealso DMPlexConstructGhostCells(), DMPlexSetGhostCellStratum(), DMPlexGetHybridBounds() 6934 @*/ 6935 PetscErrorCode DMPlexGetInteriorCellStratum(DM dm, PetscInt *cStartInterior, PetscInt *cEndInterior) 6936 { 6937 PetscInt gcEnd, cMax; 6938 PetscErrorCode ierr; 6939 6940 PetscFunctionBegin; 6941 ierr = DMPlexGetHeightStratum(dm, 0, cStartInterior, cEndInterior);CHKERRQ(ierr); 6942 ierr = DMPlexGetGhostCellStratum(dm, &gcEnd, NULL);CHKERRQ(ierr); 6943 *cEndInterior = gcEnd < 0 ? *cEndInterior : gcEnd; 6944 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6945 *cEndInterior = cMax < 0 ? *cEndInterior : cMax; 6946 PetscFunctionReturn(0); 6947 } 6948 6949 /* We can easily have a form that takes an IS instead */ 6950 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 6951 { 6952 PetscSection section, globalSection; 6953 PetscInt *numbers, p; 6954 PetscErrorCode ierr; 6955 6956 PetscFunctionBegin; 6957 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6958 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 6959 for (p = pStart; p < pEnd; ++p) { 6960 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 6961 } 6962 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 6963 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6964 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 6965 for (p = pStart; p < pEnd; ++p) { 6966 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 6967 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 6968 else numbers[p-pStart] += shift; 6969 } 6970 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 6971 if (globalSize) { 6972 PetscLayout layout; 6973 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 6974 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 6975 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 6976 } 6977 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6978 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 6979 PetscFunctionReturn(0); 6980 } 6981 6982 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 6983 { 6984 PetscInt cellHeight, cStart, cEnd, cMax; 6985 PetscErrorCode ierr; 6986 6987 PetscFunctionBegin; 6988 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 6989 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6990 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6991 if (cMax >= 0 && !includeHybrid) cEnd = PetscMin(cEnd, cMax); 6992 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 6993 PetscFunctionReturn(0); 6994 } 6995 6996 /*@ 6997 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 6998 6999 Input Parameter: 7000 . dm - The DMPlex object 7001 7002 Output Parameter: 7003 . globalCellNumbers - Global cell numbers for all cells on this process 7004 7005 Level: developer 7006 7007 .seealso DMPlexGetVertexNumbering() 7008 @*/ 7009 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7010 { 7011 DM_Plex *mesh = (DM_Plex*) dm->data; 7012 PetscErrorCode ierr; 7013 7014 PetscFunctionBegin; 7015 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7016 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 7017 *globalCellNumbers = mesh->globalCellNumbers; 7018 PetscFunctionReturn(0); 7019 } 7020 7021 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 7022 { 7023 PetscInt vStart, vEnd, vMax; 7024 PetscErrorCode ierr; 7025 7026 PetscFunctionBegin; 7027 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7028 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7029 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 7030 if (vMax >= 0 && !includeHybrid) vEnd = PetscMin(vEnd, vMax); 7031 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 7032 PetscFunctionReturn(0); 7033 } 7034 7035 /*@ 7036 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 7037 7038 Input Parameter: 7039 . dm - The DMPlex object 7040 7041 Output Parameter: 7042 . globalVertexNumbers - Global vertex numbers for all vertices on this process 7043 7044 Level: developer 7045 7046 .seealso DMPlexGetCellNumbering() 7047 @*/ 7048 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7049 { 7050 DM_Plex *mesh = (DM_Plex*) dm->data; 7051 PetscErrorCode ierr; 7052 7053 PetscFunctionBegin; 7054 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7055 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 7056 *globalVertexNumbers = mesh->globalVertexNumbers; 7057 PetscFunctionReturn(0); 7058 } 7059 7060 /*@ 7061 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 7062 7063 Input Parameter: 7064 . dm - The DMPlex object 7065 7066 Output Parameter: 7067 . globalPointNumbers - Global numbers for all points on this process 7068 7069 Level: developer 7070 7071 .seealso DMPlexGetCellNumbering() 7072 @*/ 7073 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 7074 { 7075 IS nums[4]; 7076 PetscInt depths[4], gdepths[4], starts[4]; 7077 PetscInt depth, d, shift = 0; 7078 PetscErrorCode ierr; 7079 7080 PetscFunctionBegin; 7081 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7082 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7083 /* For unstratified meshes use dim instead of depth */ 7084 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 7085 for (d = 0; d <= depth; ++d) { 7086 PetscInt end; 7087 7088 depths[d] = depth-d; 7089 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 7090 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 7091 } 7092 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 7093 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 7094 for (d = 0; d <= depth; ++d) { 7095 if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 7096 } 7097 for (d = 0; d <= depth; ++d) { 7098 PetscInt pStart, pEnd, gsize; 7099 7100 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 7101 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 7102 shift += gsize; 7103 } 7104 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 7105 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 7106 PetscFunctionReturn(0); 7107 } 7108 7109 7110 /*@ 7111 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 7112 7113 Input Parameter: 7114 . dm - The DMPlex object 7115 7116 Output Parameter: 7117 . ranks - The rank field 7118 7119 Options Database Keys: 7120 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 7121 7122 Level: intermediate 7123 7124 .seealso: DMView() 7125 @*/ 7126 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 7127 { 7128 DM rdm; 7129 PetscFE fe; 7130 PetscScalar *r; 7131 PetscMPIInt rank; 7132 PetscInt dim, cStart, cEnd, c; 7133 PetscErrorCode ierr; 7134 7135 PetscFunctionBeginUser; 7136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7137 PetscValidPointer(ranks, 2); 7138 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 7139 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 7140 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 7141 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 7142 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 7143 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 7144 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 7145 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 7146 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7147 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 7148 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 7149 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 7150 for (c = cStart; c < cEnd; ++c) { 7151 PetscScalar *lr; 7152 7153 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 7154 if (lr) *lr = rank; 7155 } 7156 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 7157 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 7158 PetscFunctionReturn(0); 7159 } 7160 7161 /*@ 7162 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 7163 7164 Input Parameters: 7165 + dm - The DMPlex 7166 - label - The DMLabel 7167 7168 Output Parameter: 7169 . val - The label value field 7170 7171 Options Database Keys: 7172 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 7173 7174 Level: intermediate 7175 7176 .seealso: DMView() 7177 @*/ 7178 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 7179 { 7180 DM rdm; 7181 PetscFE fe; 7182 PetscScalar *v; 7183 PetscInt dim, cStart, cEnd, c; 7184 PetscErrorCode ierr; 7185 7186 PetscFunctionBeginUser; 7187 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7188 PetscValidPointer(label, 2); 7189 PetscValidPointer(val, 3); 7190 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 7191 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 7192 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 7193 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 7194 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 7195 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 7196 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 7197 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7198 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 7199 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 7200 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 7201 for (c = cStart; c < cEnd; ++c) { 7202 PetscScalar *lv; 7203 PetscInt cval; 7204 7205 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 7206 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 7207 *lv = cval; 7208 } 7209 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 7210 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 7211 PetscFunctionReturn(0); 7212 } 7213 7214 /*@ 7215 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 7216 7217 Input Parameter: 7218 . dm - The DMPlex object 7219 7220 Notes: 7221 This is a useful diagnostic when creating meshes programmatically. 7222 7223 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7224 7225 Level: developer 7226 7227 .seealso: DMCreate(), DMSetFromOptions() 7228 @*/ 7229 PetscErrorCode DMPlexCheckSymmetry(DM dm) 7230 { 7231 PetscSection coneSection, supportSection; 7232 const PetscInt *cone, *support; 7233 PetscInt coneSize, c, supportSize, s; 7234 PetscInt pStart, pEnd, p, pp, csize, ssize; 7235 PetscBool storagecheck = PETSC_TRUE; 7236 PetscErrorCode ierr; 7237 7238 PetscFunctionBegin; 7239 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7240 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 7241 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 7242 /* Check that point p is found in the support of its cone points, and vice versa */ 7243 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7244 for (p = pStart; p < pEnd; ++p) { 7245 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 7246 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 7247 for (c = 0; c < coneSize; ++c) { 7248 PetscBool dup = PETSC_FALSE; 7249 PetscInt d; 7250 for (d = c-1; d >= 0; --d) { 7251 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 7252 } 7253 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 7254 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 7255 for (s = 0; s < supportSize; ++s) { 7256 if (support[s] == p) break; 7257 } 7258 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 7259 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 7260 for (s = 0; s < coneSize; ++s) { 7261 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 7262 } 7263 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7264 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 7265 for (s = 0; s < supportSize; ++s) { 7266 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 7267 } 7268 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7269 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 7270 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 7271 } 7272 } 7273 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 7274 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 7275 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 7276 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 7277 for (s = 0; s < supportSize; ++s) { 7278 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 7279 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 7280 for (c = 0; c < coneSize; ++c) { 7281 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 7282 if (cone[c] != pp) { c = 0; break; } 7283 if (cone[c] == p) break; 7284 } 7285 if (c >= coneSize) { 7286 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 7287 for (c = 0; c < supportSize; ++c) { 7288 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 7289 } 7290 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7291 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 7292 for (c = 0; c < coneSize; ++c) { 7293 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 7294 } 7295 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7296 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 7297 } 7298 } 7299 } 7300 if (storagecheck) { 7301 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 7302 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 7303 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 7304 } 7305 PetscFunctionReturn(0); 7306 } 7307 7308 /*@ 7309 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 7310 7311 Input Parameters: 7312 + dm - The DMPlex object 7313 - cellHeight - Normally 0 7314 7315 Notes: 7316 This is a useful diagnostic when creating meshes programmatically. 7317 Currently applicable only to homogeneous simplex or tensor meshes. 7318 7319 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7320 7321 Level: developer 7322 7323 .seealso: DMCreate(), DMSetFromOptions() 7324 @*/ 7325 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 7326 { 7327 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 7328 PetscBool isSimplex = PETSC_FALSE; 7329 PetscErrorCode ierr; 7330 7331 PetscFunctionBegin; 7332 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7333 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7334 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 7335 if (cStart < cEnd) { 7336 ierr = DMPlexGetConeSize(dm, cStart, &c);CHKERRQ(ierr); 7337 isSimplex = c == dim+1 ? PETSC_TRUE : PETSC_FALSE; 7338 } 7339 switch (dim) { 7340 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 7341 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 7342 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 7343 default: 7344 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %D", dim); 7345 } 7346 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7347 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7348 cMax = cMax >= 0 ? cMax : cEnd; 7349 for (c = cStart; c < cMax; ++c) { 7350 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 7351 7352 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7353 for (cl = 0; cl < closureSize*2; cl += 2) { 7354 const PetscInt p = closure[cl]; 7355 if ((p >= vStart) && (p < vEnd)) ++coneSize; 7356 } 7357 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7358 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D vertices != %D", c, coneSize, numCorners); 7359 } 7360 for (c = cMax; c < cEnd; ++c) { 7361 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 7362 7363 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7364 for (cl = 0; cl < closureSize*2; cl += 2) { 7365 const PetscInt p = closure[cl]; 7366 if ((p >= vStart) && (p < vEnd)) ++coneSize; 7367 } 7368 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7369 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %D has %D vertices > %D", c, coneSize, numHybridCorners); 7370 } 7371 PetscFunctionReturn(0); 7372 } 7373 7374 /*@ 7375 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 7376 7377 Not Collective 7378 7379 Input Parameters: 7380 + dm - The DMPlex object 7381 - cellHeight - Normally 0 7382 7383 Notes: 7384 This is a useful diagnostic when creating meshes programmatically. 7385 This routine is only relevant for meshes that are fully interpolated across all ranks. 7386 It will error out if a partially interpolated mesh is given on some rank. 7387 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 7388 7389 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7390 7391 Level: developer 7392 7393 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 7394 @*/ 7395 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 7396 { 7397 PetscInt pMax[4]; 7398 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 7399 PetscErrorCode ierr; 7400 DMPlexInterpolatedFlag interpEnum; 7401 7402 PetscFunctionBegin; 7403 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7404 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 7405 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 7406 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 7407 PetscMPIInt rank; 7408 MPI_Comm comm; 7409 7410 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 7411 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 7412 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 7413 } 7414 7415 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7416 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7417 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7418 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 7419 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 7420 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 7421 for (c = cStart; c < cEnd; ++c) { 7422 const PetscInt *cone, *ornt, *faces; 7423 DMPolytopeType ct; 7424 PetscInt numFaces, faceSize, coneSize,f; 7425 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 7426 7427 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 7428 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 7429 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7430 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 7431 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 7432 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7433 for (cl = 0; cl < closureSize*2; cl += 2) { 7434 const PetscInt p = closure[cl]; 7435 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 7436 } 7437 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 7438 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D faces but should have %D", c, coneSize, numFaces); 7439 for (f = 0; f < numFaces; ++f) { 7440 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 7441 7442 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 7443 for (cl = 0; cl < fclosureSize*2; cl += 2) { 7444 const PetscInt p = fclosure[cl]; 7445 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 7446 } 7447 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); 7448 for (v = 0; v < fnumCorners; ++v) { 7449 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]); 7450 } 7451 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 7452 } 7453 ierr = DMPlexRestoreFaces_Internal(dm, ct, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 7454 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7455 } 7456 } 7457 PetscFunctionReturn(0); 7458 } 7459 7460 /*@ 7461 DMPlexCheckGeometry - Check the geometry of mesh cells 7462 7463 Input Parameter: 7464 . dm - The DMPlex object 7465 7466 Notes: 7467 This is a useful diagnostic when creating meshes programmatically. 7468 7469 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7470 7471 Level: developer 7472 7473 .seealso: DMCreate(), DMSetFromOptions() 7474 @*/ 7475 PetscErrorCode DMPlexCheckGeometry(DM dm) 7476 { 7477 PetscReal detJ, J[9], refVol = 1.0; 7478 PetscReal vol; 7479 PetscInt dim, depth, d, cStart, cEnd, c, cMax; 7480 PetscErrorCode ierr; 7481 7482 PetscFunctionBegin; 7483 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7484 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7485 for (d = 0; d < dim; ++d) refVol *= 2.0; 7486 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7487 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7488 cMax = cMax < 0 ? cEnd : cMax; 7489 for (c = cStart; c < cMax; ++c) { 7490 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 7491 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted, |J| = %g", c, (double) detJ); 7492 ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 7493 if (depth > 1) { 7494 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 7495 if (vol <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %d is inverted, vol = %g", c, (double) vol); 7496 ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 7497 } 7498 } 7499 PetscFunctionReturn(0); 7500 } 7501 7502 /*@ 7503 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 7504 7505 Input Parameters: 7506 . dm - The DMPlex object 7507 7508 Notes: 7509 This is mainly intended for debugging/testing purposes. 7510 It currently checks only meshes with no partition overlapping. 7511 7512 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7513 7514 Level: developer 7515 7516 .seealso: DMGetPointSF(), DMSetFromOptions() 7517 @*/ 7518 PetscErrorCode DMPlexCheckPointSF(DM dm) 7519 { 7520 PetscSF pointSF; 7521 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 7522 const PetscInt *locals, *rootdegree; 7523 PetscBool distributed; 7524 PetscErrorCode ierr; 7525 7526 PetscFunctionBegin; 7527 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7528 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 7529 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 7530 if (!distributed) PetscFunctionReturn(0); 7531 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 7532 if (overlap) { 7533 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping"); 7534 PetscFunctionReturn(0); 7535 } 7536 if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 7537 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 7538 if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 7539 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 7540 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 7541 7542 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 7543 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7544 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 7545 for (l = 0; l < nleaves; ++l) { 7546 const PetscInt point = locals[l]; 7547 7548 if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 7549 } 7550 7551 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 7552 for (l = 0; l < nleaves; ++l) { 7553 const PetscInt point = locals[l]; 7554 const PetscInt *cone; 7555 PetscInt coneSize, c, idx; 7556 7557 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 7558 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 7559 for (c = 0; c < coneSize; ++c) { 7560 if (!rootdegree[cone[c]]) { 7561 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 7562 if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 7563 } 7564 } 7565 } 7566 PetscFunctionReturn(0); 7567 } 7568 7569 typedef struct cell_stats 7570 { 7571 PetscReal min, max, sum, squaresum; 7572 PetscInt count; 7573 } cell_stats_t; 7574 7575 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 7576 { 7577 PetscInt i, N = *len; 7578 7579 for (i = 0; i < N; i++) { 7580 cell_stats_t *A = (cell_stats_t *) a; 7581 cell_stats_t *B = (cell_stats_t *) b; 7582 7583 B->min = PetscMin(A->min,B->min); 7584 B->max = PetscMax(A->max,B->max); 7585 B->sum += A->sum; 7586 B->squaresum += A->squaresum; 7587 B->count += A->count; 7588 } 7589 } 7590 7591 /*@ 7592 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 7593 7594 Collective on dm 7595 7596 Input Parameters: 7597 + dm - The DMPlex object 7598 . output - If true, statistics will be displayed on stdout 7599 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 7600 7601 Notes: 7602 This is mainly intended for debugging/testing purposes. 7603 7604 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7605 7606 Level: developer 7607 7608 .seealso: DMSetFromOptions() 7609 @*/ 7610 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 7611 { 7612 DM dmCoarse; 7613 cell_stats_t stats, globalStats; 7614 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 7615 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 7616 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 7617 PetscInt cdim, cStart, cEnd, cMax, c, eStart, eEnd, count = 0; 7618 PetscMPIInt rank,size; 7619 PetscErrorCode ierr; 7620 7621 PetscFunctionBegin; 7622 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7623 stats.min = PETSC_MAX_REAL; 7624 stats.max = PETSC_MIN_REAL; 7625 stats.sum = stats.squaresum = 0.; 7626 stats.count = 0; 7627 7628 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 7629 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 7630 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 7631 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 7632 ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 7633 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 7634 ierr = DMPlexGetHybridBounds(dm,&cMax,NULL,NULL,NULL);CHKERRQ(ierr); 7635 cMax = cMax < 0 ? cEnd : cMax; 7636 for (c = cStart; c < cMax; c++) { 7637 PetscInt i; 7638 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 7639 7640 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 7641 if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 7642 for (i = 0; i < PetscSqr(cdim); ++i) { 7643 frobJ += J[i] * J[i]; 7644 frobInvJ += invJ[i] * invJ[i]; 7645 } 7646 cond2 = frobJ * frobInvJ; 7647 cond = PetscSqrtReal(cond2); 7648 7649 stats.min = PetscMin(stats.min,cond); 7650 stats.max = PetscMax(stats.max,cond); 7651 stats.sum += cond; 7652 stats.squaresum += cond2; 7653 stats.count++; 7654 if (output && cond > limit) { 7655 PetscSection coordSection; 7656 Vec coordsLocal; 7657 PetscScalar *coords = NULL; 7658 PetscInt Nv, d, clSize, cl, *closure = NULL; 7659 7660 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7661 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7662 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 7663 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 7664 for (i = 0; i < Nv/cdim; ++i) { 7665 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 7666 for (d = 0; d < cdim; ++d) { 7667 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 7668 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 7669 } 7670 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 7671 } 7672 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 7673 for (cl = 0; cl < clSize*2; cl += 2) { 7674 const PetscInt edge = closure[cl]; 7675 7676 if ((edge >= eStart) && (edge < eEnd)) { 7677 PetscReal len; 7678 7679 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 7680 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 7681 } 7682 } 7683 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 7684 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 7685 } 7686 } 7687 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 7688 7689 if (size > 1) { 7690 PetscMPIInt blockLengths[2] = {4,1}; 7691 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 7692 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 7693 MPI_Op statReduce; 7694 7695 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRQ(ierr); 7696 ierr = MPI_Type_commit(&statType);CHKERRQ(ierr); 7697 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRQ(ierr); 7698 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRQ(ierr); 7699 ierr = MPI_Op_free(&statReduce);CHKERRQ(ierr); 7700 ierr = MPI_Type_free(&statType);CHKERRQ(ierr); 7701 } else { 7702 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 7703 } 7704 if (!rank) { 7705 count = globalStats.count; 7706 min = globalStats.min; 7707 max = globalStats.max; 7708 mean = globalStats.sum / globalStats.count; 7709 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 7710 } 7711 7712 if (output) { 7713 ierr = PetscPrintf(comm,"Mesh with %D cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double) min, (double) max, (double) mean, (double) stdev);CHKERRQ(ierr); 7714 } 7715 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 7716 7717 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 7718 if (dmCoarse) { 7719 PetscBool isplex; 7720 7721 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 7722 if (isplex) { 7723 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 7724 } 7725 } 7726 PetscFunctionReturn(0); 7727 } 7728 7729 /* Pointwise interpolation 7730 Just code FEM for now 7731 u^f = I u^c 7732 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 7733 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 7734 I_{ij} = psi^f_i phi^c_j 7735 */ 7736 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 7737 { 7738 PetscSection gsc, gsf; 7739 PetscInt m, n; 7740 void *ctx; 7741 DM cdm; 7742 PetscBool regular, ismatis; 7743 PetscErrorCode ierr; 7744 7745 PetscFunctionBegin; 7746 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 7747 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 7748 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 7749 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 7750 7751 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 7752 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 7753 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 7754 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 7755 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 7756 7757 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 7758 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 7759 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 7760 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 7761 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 7762 if (scaling) { 7763 /* Use naive scaling */ 7764 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 7765 } 7766 PetscFunctionReturn(0); 7767 } 7768 7769 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 7770 { 7771 PetscErrorCode ierr; 7772 VecScatter ctx; 7773 7774 PetscFunctionBegin; 7775 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 7776 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 7777 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 7778 PetscFunctionReturn(0); 7779 } 7780 7781 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 7782 { 7783 PetscSection gsc, gsf; 7784 PetscInt m, n; 7785 void *ctx; 7786 DM cdm; 7787 PetscBool regular; 7788 PetscErrorCode ierr; 7789 7790 PetscFunctionBegin; 7791 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 7792 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 7793 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 7794 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 7795 7796 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 7797 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 7798 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 7799 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 7800 7801 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 7802 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 7803 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 7804 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 7805 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 7806 PetscFunctionReturn(0); 7807 } 7808 7809 /*@ 7810 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 7811 7812 Input Parameter: 7813 . dm - The DMPlex object 7814 7815 Output Parameter: 7816 . regular - The flag 7817 7818 Level: intermediate 7819 7820 .seealso: DMPlexSetRegularRefinement() 7821 @*/ 7822 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 7823 { 7824 PetscFunctionBegin; 7825 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7826 PetscValidPointer(regular, 2); 7827 *regular = ((DM_Plex *) dm->data)->regularRefinement; 7828 PetscFunctionReturn(0); 7829 } 7830 7831 /*@ 7832 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 7833 7834 Input Parameters: 7835 + dm - The DMPlex object 7836 - regular - The flag 7837 7838 Level: intermediate 7839 7840 .seealso: DMPlexGetRegularRefinement() 7841 @*/ 7842 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 7843 { 7844 PetscFunctionBegin; 7845 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7846 ((DM_Plex *) dm->data)->regularRefinement = regular; 7847 PetscFunctionReturn(0); 7848 } 7849 7850 /* anchors */ 7851 /*@ 7852 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 7853 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 7854 7855 not collective 7856 7857 Input Parameters: 7858 . dm - The DMPlex object 7859 7860 Output Parameters: 7861 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 7862 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 7863 7864 7865 Level: intermediate 7866 7867 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 7868 @*/ 7869 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 7870 { 7871 DM_Plex *plex = (DM_Plex *)dm->data; 7872 PetscErrorCode ierr; 7873 7874 PetscFunctionBegin; 7875 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7876 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 7877 if (anchorSection) *anchorSection = plex->anchorSection; 7878 if (anchorIS) *anchorIS = plex->anchorIS; 7879 PetscFunctionReturn(0); 7880 } 7881 7882 /*@ 7883 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 7884 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 7885 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 7886 7887 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 7888 DMGetConstraints() and filling in the entries in the constraint matrix. 7889 7890 collective on dm 7891 7892 Input Parameters: 7893 + dm - The DMPlex object 7894 . 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). 7895 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 7896 7897 The reference counts of anchorSection and anchorIS are incremented. 7898 7899 Level: intermediate 7900 7901 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 7902 @*/ 7903 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 7904 { 7905 DM_Plex *plex = (DM_Plex *)dm->data; 7906 PetscMPIInt result; 7907 PetscErrorCode ierr; 7908 7909 PetscFunctionBegin; 7910 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7911 if (anchorSection) { 7912 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 7913 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 7914 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 7915 } 7916 if (anchorIS) { 7917 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 7918 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 7919 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 7920 } 7921 7922 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 7923 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 7924 plex->anchorSection = anchorSection; 7925 7926 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 7927 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 7928 plex->anchorIS = anchorIS; 7929 7930 #if defined(PETSC_USE_DEBUG) 7931 if (anchorIS && anchorSection) { 7932 PetscInt size, a, pStart, pEnd; 7933 const PetscInt *anchors; 7934 7935 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 7936 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 7937 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 7938 for (a = 0; a < size; a++) { 7939 PetscInt p; 7940 7941 p = anchors[a]; 7942 if (p >= pStart && p < pEnd) { 7943 PetscInt dof; 7944 7945 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 7946 if (dof) { 7947 PetscErrorCode ierr2; 7948 7949 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 7950 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 7951 } 7952 } 7953 } 7954 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 7955 } 7956 #endif 7957 /* reset the generic constraints */ 7958 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 7959 PetscFunctionReturn(0); 7960 } 7961 7962 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 7963 { 7964 PetscSection anchorSection; 7965 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 7966 PetscErrorCode ierr; 7967 7968 PetscFunctionBegin; 7969 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7970 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 7971 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 7972 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 7973 if (numFields) { 7974 PetscInt f; 7975 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 7976 7977 for (f = 0; f < numFields; f++) { 7978 PetscInt numComp; 7979 7980 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 7981 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 7982 } 7983 } 7984 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 7985 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 7986 pStart = PetscMax(pStart,sStart); 7987 pEnd = PetscMin(pEnd,sEnd); 7988 pEnd = PetscMax(pStart,pEnd); 7989 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 7990 for (p = pStart; p < pEnd; p++) { 7991 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 7992 if (dof) { 7993 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 7994 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 7995 for (f = 0; f < numFields; f++) { 7996 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 7997 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 7998 } 7999 } 8000 } 8001 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 8002 PetscFunctionReturn(0); 8003 } 8004 8005 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 8006 { 8007 PetscSection aSec; 8008 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 8009 const PetscInt *anchors; 8010 PetscInt numFields, f; 8011 IS aIS; 8012 PetscErrorCode ierr; 8013 8014 PetscFunctionBegin; 8015 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8016 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 8017 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 8018 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 8019 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 8020 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 8021 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 8022 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 8023 /* cSec will be a subset of aSec and section */ 8024 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 8025 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 8026 i[0] = 0; 8027 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 8028 for (p = pStart; p < pEnd; p++) { 8029 PetscInt rDof, rOff, r; 8030 8031 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 8032 if (!rDof) continue; 8033 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 8034 if (numFields) { 8035 for (f = 0; f < numFields; f++) { 8036 annz = 0; 8037 for (r = 0; r < rDof; r++) { 8038 a = anchors[rOff + r]; 8039 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 8040 annz += aDof; 8041 } 8042 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 8043 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 8044 for (q = 0; q < dof; q++) { 8045 i[off + q + 1] = i[off + q] + annz; 8046 } 8047 } 8048 } 8049 else { 8050 annz = 0; 8051 for (q = 0; q < dof; q++) { 8052 a = anchors[off + q]; 8053 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 8054 annz += aDof; 8055 } 8056 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 8057 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 8058 for (q = 0; q < dof; q++) { 8059 i[off + q + 1] = i[off + q] + annz; 8060 } 8061 } 8062 } 8063 nnz = i[m]; 8064 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 8065 offset = 0; 8066 for (p = pStart; p < pEnd; p++) { 8067 if (numFields) { 8068 for (f = 0; f < numFields; f++) { 8069 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 8070 for (q = 0; q < dof; q++) { 8071 PetscInt rDof, rOff, r; 8072 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 8073 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 8074 for (r = 0; r < rDof; r++) { 8075 PetscInt s; 8076 8077 a = anchors[rOff + r]; 8078 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 8079 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 8080 for (s = 0; s < aDof; s++) { 8081 j[offset++] = aOff + s; 8082 } 8083 } 8084 } 8085 } 8086 } 8087 else { 8088 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 8089 for (q = 0; q < dof; q++) { 8090 PetscInt rDof, rOff, r; 8091 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 8092 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 8093 for (r = 0; r < rDof; r++) { 8094 PetscInt s; 8095 8096 a = anchors[rOff + r]; 8097 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 8098 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 8099 for (s = 0; s < aDof; s++) { 8100 j[offset++] = aOff + s; 8101 } 8102 } 8103 } 8104 } 8105 } 8106 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 8107 ierr = PetscFree(i);CHKERRQ(ierr); 8108 ierr = PetscFree(j);CHKERRQ(ierr); 8109 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 8110 PetscFunctionReturn(0); 8111 } 8112 8113 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 8114 { 8115 DM_Plex *plex = (DM_Plex *)dm->data; 8116 PetscSection anchorSection, section, cSec; 8117 Mat cMat; 8118 PetscErrorCode ierr; 8119 8120 PetscFunctionBegin; 8121 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8122 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 8123 if (anchorSection) { 8124 PetscInt Nf; 8125 8126 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 8127 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 8128 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 8129 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 8130 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 8131 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 8132 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 8133 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 8134 } 8135 PetscFunctionReturn(0); 8136 } 8137 8138 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 8139 { 8140 IS subis; 8141 PetscSection section, subsection; 8142 PetscErrorCode ierr; 8143 8144 PetscFunctionBegin; 8145 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 8146 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 8147 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 8148 /* Create subdomain */ 8149 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 8150 /* Create submodel */ 8151 ierr = DMPlexCreateSubpointIS(*subdm, &subis);CHKERRQ(ierr); 8152 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 8153 ierr = ISDestroy(&subis);CHKERRQ(ierr); 8154 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 8155 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 8156 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 8157 /* Create map from submodel to global model */ 8158 if (is) { 8159 PetscSection sectionGlobal, subsectionGlobal; 8160 IS spIS; 8161 const PetscInt *spmap; 8162 PetscInt *subIndices; 8163 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 8164 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 8165 8166 ierr = DMPlexCreateSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 8167 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 8168 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 8169 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 8170 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 8171 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 8172 for (p = pStart; p < pEnd; ++p) { 8173 PetscInt gdof, pSubSize = 0; 8174 8175 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 8176 if (gdof > 0) { 8177 for (f = 0; f < Nf; ++f) { 8178 PetscInt fdof, fcdof; 8179 8180 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 8181 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 8182 pSubSize += fdof-fcdof; 8183 } 8184 subSize += pSubSize; 8185 if (pSubSize) { 8186 if (bs < 0) { 8187 bs = pSubSize; 8188 } else if (bs != pSubSize) { 8189 /* Layout does not admit a pointwise block size */ 8190 bs = 1; 8191 } 8192 } 8193 } 8194 } 8195 /* Must have same blocksize on all procs (some might have no points) */ 8196 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 8197 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 8198 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 8199 else {bs = bsMinMax[0];} 8200 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 8201 for (p = pStart; p < pEnd; ++p) { 8202 PetscInt gdof, goff; 8203 8204 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 8205 if (gdof > 0) { 8206 const PetscInt point = spmap[p]; 8207 8208 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 8209 for (f = 0; f < Nf; ++f) { 8210 PetscInt fdof, fcdof, fc, f2, poff = 0; 8211 8212 /* Can get rid of this loop by storing field information in the global section */ 8213 for (f2 = 0; f2 < f; ++f2) { 8214 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 8215 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 8216 poff += fdof-fcdof; 8217 } 8218 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8219 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8220 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 8221 subIndices[subOff] = goff+poff+fc; 8222 } 8223 } 8224 } 8225 } 8226 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 8227 ierr = ISDestroy(&spIS);CHKERRQ(ierr); 8228 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 8229 if (bs > 1) { 8230 /* We need to check that the block size does not come from non-contiguous fields */ 8231 PetscInt i, j, set = 1; 8232 for (i = 0; i < subSize; i += bs) { 8233 for (j = 0; j < bs; ++j) { 8234 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 8235 } 8236 } 8237 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 8238 } 8239 /* Attach nullspace */ 8240 for (f = 0; f < Nf; ++f) { 8241 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 8242 if ((*subdm)->nullspaceConstructors[f]) break; 8243 } 8244 if (f < Nf) { 8245 MatNullSpace nullSpace; 8246 8247 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, &nullSpace);CHKERRQ(ierr); 8248 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 8249 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 8250 } 8251 } 8252 PetscFunctionReturn(0); 8253 } 8254 8255 /*@ 8256 DMPlexMonitorThroughput - Report the cell throughput of FE integration 8257 8258 Input Parameter: 8259 - dm - The DM 8260 8261 Level: developer 8262 8263 Options Database Keys: 8264 . -dm_plex_monitor_throughput - Activate the monitor 8265 8266 .seealso: DMSetFromOptions(), DMPlexCreate() 8267 @*/ 8268 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 8269 { 8270 PetscStageLog stageLog; 8271 PetscLogEvent event; 8272 PetscLogStage stage; 8273 PetscEventPerfInfo eventInfo; 8274 PetscReal cellRate, flopRate; 8275 PetscInt cStart, cEnd, Nf, N; 8276 const char *name; 8277 PetscErrorCode ierr; 8278 8279 PetscFunctionBegin; 8280 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8281 #if defined(PETSC_USE_LOG) 8282 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 8283 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8284 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 8285 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 8286 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 8287 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 8288 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 8289 N = (cEnd - cStart)*Nf*eventInfo.count; 8290 flopRate = eventInfo.flops/eventInfo.time; 8291 cellRate = N/eventInfo.time; 8292 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "DM (%s) FE Residual Integration: %D integrals %D reps\n Cell rate: %.2g/s flop rate: %.2g MF/s\n", name ? name : "unknown", N, eventInfo.count, (double) cellRate, (double) (flopRate/1.e6));CHKERRQ(ierr); 8293 #else 8294 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 8295 #endif 8296 PetscFunctionReturn(0); 8297 } 8298