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 #include <petscdmplextransform.h> 10 11 /* Logging support */ 12 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,DMPLEX_LocatePoints,DMPLEX_TopologyView,DMPLEX_LabelsView,DMPLEX_CoordinatesView,DMPLEX_SectionView,DMPLEX_GlobalVectorView,DMPLEX_LocalVectorView,DMPLEX_TopologyLoad,DMPLEX_LabelsLoad,DMPLEX_CoordinatesLoad,DMPLEX_SectionLoad,DMPLEX_GlobalVectorLoad,DMPLEX_LocalVectorLoad; 13 14 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 15 16 /*@ 17 DMPlexIsSimplex - Is the first cell in this mesh a simplex? 18 19 Input Parameter: 20 . dm - The DMPlex object 21 22 Output Parameter: 23 . simplex - Flag checking for a simplex 24 25 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 26 If the mesh has no cells, this returns PETSC_FALSE. 27 28 Level: intermediate 29 30 .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices() 31 @*/ 32 PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 33 { 34 DMPolytopeType ct; 35 PetscInt cStart, cEnd; 36 PetscErrorCode ierr; 37 38 PetscFunctionBegin; 39 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 40 if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 41 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 42 *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 43 PetscFunctionReturn(0); 44 } 45 46 /*@ 47 DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 48 49 Input Parameters: 50 + dm - The DMPlex object 51 - height - The cell height in the Plex, 0 is the default 52 53 Output Parameters: 54 + cStart - The first "normal" cell 55 - cEnd - The upper bound on "normal"" cells 56 57 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 58 59 Level: developer 60 61 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 62 @*/ 63 PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 64 { 65 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 66 PetscInt cS, cE, c; 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr); 71 for (c = cS; c < cE; ++c) { 72 DMPolytopeType cct; 73 74 ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr); 75 if ((PetscInt) cct < 0) break; 76 switch (cct) { 77 case DM_POLYTOPE_POINT: 78 case DM_POLYTOPE_SEGMENT: 79 case DM_POLYTOPE_TRIANGLE: 80 case DM_POLYTOPE_QUADRILATERAL: 81 case DM_POLYTOPE_TETRAHEDRON: 82 case DM_POLYTOPE_HEXAHEDRON: 83 ct = cct; 84 break; 85 default: break; 86 } 87 if (ct != DM_POLYTOPE_UNKNOWN) break; 88 } 89 if (ct != DM_POLYTOPE_UNKNOWN) { 90 DMLabel ctLabel; 91 92 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 93 ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr); 94 } 95 if (cStart) *cStart = cS; 96 if (cEnd) *cEnd = cE; 97 PetscFunctionReturn(0); 98 } 99 100 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 101 { 102 PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 103 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 104 PetscErrorCode ierr; 105 106 PetscFunctionBegin; 107 *ft = PETSC_VTK_INVALID; 108 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 109 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 110 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 111 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 112 if (field >= 0) { 113 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 114 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 115 } else { 116 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 117 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 118 } 119 ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 120 if (globalvcdof[0]) { 121 *sStart = vStart; 122 *sEnd = vEnd; 123 if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 124 else *ft = PETSC_VTK_POINT_FIELD; 125 } else if (globalvcdof[1]) { 126 *sStart = cStart; 127 *sEnd = cEnd; 128 if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 129 else *ft = PETSC_VTK_CELL_FIELD; 130 } else { 131 if (field >= 0) { 132 const char *fieldname; 133 134 ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 135 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 136 } else { 137 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr); 138 } 139 } 140 PetscFunctionReturn(0); 141 } 142 143 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 144 { 145 DM dm; 146 PetscSection s; 147 PetscDraw draw, popup; 148 DM cdm; 149 PetscSection coordSection; 150 Vec coordinates; 151 const PetscScalar *coords, *array; 152 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 153 PetscReal vbound[2], time; 154 PetscBool isnull, flg; 155 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 156 const char *name; 157 char title[PETSC_MAX_PATH_LEN]; 158 PetscErrorCode ierr; 159 160 PetscFunctionBegin; 161 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 162 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 163 if (isnull) PetscFunctionReturn(0); 164 165 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 166 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 167 PetscCheckFalse(dim != 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 168 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 169 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 170 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 171 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 172 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 173 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 174 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 175 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 176 177 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 178 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 179 180 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 181 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 182 for (c = 0; c < N; c += dim) { 183 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 184 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 185 } 186 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 187 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 188 189 /* Could implement something like DMDASelectFields() */ 190 for (f = 0; f < Nf; ++f) { 191 DM fdm = dm; 192 Vec fv = v; 193 IS fis; 194 char prefix[PETSC_MAX_PATH_LEN]; 195 const char *fname; 196 197 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 198 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 199 200 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 201 else {prefix[0] = '\0';} 202 if (Nf > 1) { 203 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 204 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 205 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 206 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 207 } 208 for (comp = 0; comp < Nc; ++comp, ++w) { 209 PetscInt nmax = 2; 210 211 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 212 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 213 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 214 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 215 216 /* TODO Get max and min only for this component */ 217 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 218 if (!flg) { 219 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 220 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 221 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 222 } 223 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 224 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 225 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 226 227 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 228 for (c = cStart; c < cEnd; ++c) { 229 PetscScalar *coords = NULL, *a = NULL; 230 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 231 232 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 233 if (a) { 234 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 235 color[1] = color[2] = color[3] = color[0]; 236 } else { 237 PetscScalar *vals = NULL; 238 PetscInt numVals, va; 239 240 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 241 PetscCheckFalse(numVals % Nc,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); 242 switch (numVals/Nc) { 243 case 3: /* P1 Triangle */ 244 case 4: /* P1 Quadrangle */ 245 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 246 break; 247 case 6: /* P2 Triangle */ 248 case 8: /* P2 Quadrangle */ 249 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 250 break; 251 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 252 } 253 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 254 } 255 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 256 switch (numCoords) { 257 case 6: 258 case 12: /* Localized triangle */ 259 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); 260 break; 261 case 8: 262 case 16: /* Localized quadrilateral */ 263 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); 264 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); 265 break; 266 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 267 } 268 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 269 } 270 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 271 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 272 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 273 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 274 } 275 if (Nf > 1) { 276 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 277 ierr = ISDestroy(&fis);CHKERRQ(ierr); 278 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 279 } 280 } 281 PetscFunctionReturn(0); 282 } 283 284 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 285 { 286 DM dm; 287 Vec locv; 288 const char *name; 289 PetscSection section; 290 PetscInt pStart, pEnd; 291 PetscInt numFields; 292 PetscViewerVTKFieldType ft; 293 PetscErrorCode ierr; 294 295 PetscFunctionBegin; 296 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 297 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 298 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 299 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 300 ierr = VecCopy(v, locv);CHKERRQ(ierr); 301 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 302 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 303 if (!numFields) { 304 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 305 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 306 } else { 307 PetscInt f; 308 309 for (f = 0; f < numFields; f++) { 310 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 311 if (ft == PETSC_VTK_INVALID) continue; 312 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 313 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 314 } 315 ierr = VecDestroy(&locv);CHKERRQ(ierr); 316 } 317 PetscFunctionReturn(0); 318 } 319 320 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 321 { 322 DM dm; 323 PetscBool isvtk, ishdf5, isdraw, isglvis; 324 PetscErrorCode ierr; 325 326 PetscFunctionBegin; 327 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 328 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 330 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 331 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 332 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 333 if (isvtk || ishdf5 || isdraw || isglvis) { 334 PetscInt i,numFields; 335 PetscObject fe; 336 PetscBool fem = PETSC_FALSE; 337 Vec locv = v; 338 const char *name; 339 PetscInt step; 340 PetscReal time; 341 342 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 343 for (i=0; i<numFields; i++) { 344 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 345 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 346 } 347 if (fem) { 348 PetscObject isZero; 349 350 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 351 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 352 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 353 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 354 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 355 ierr = VecCopy(v, locv);CHKERRQ(ierr); 356 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 357 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 358 } 359 if (isvtk) { 360 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 361 } else if (ishdf5) { 362 #if defined(PETSC_HAVE_HDF5) 363 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 364 #else 365 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 366 #endif 367 } else if (isdraw) { 368 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 369 } else if (isglvis) { 370 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 371 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 372 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 373 } 374 if (fem) { 375 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 376 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 377 } 378 } else { 379 PetscBool isseq; 380 381 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 382 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 383 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 384 } 385 PetscFunctionReturn(0); 386 } 387 388 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 389 { 390 DM dm; 391 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 392 PetscErrorCode ierr; 393 394 PetscFunctionBegin; 395 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 396 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 397 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 399 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 400 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 401 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 402 if (isvtk || isdraw || isglvis) { 403 Vec locv; 404 PetscObject isZero; 405 const char *name; 406 407 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 408 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 409 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 410 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 411 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 412 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 413 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 414 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 415 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 416 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 417 } else if (ishdf5) { 418 #if defined(PETSC_HAVE_HDF5) 419 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 420 #else 421 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 422 #endif 423 } else if (isexodusii) { 424 #if defined(PETSC_HAVE_EXODUSII) 425 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 426 #else 427 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 428 #endif 429 } else { 430 PetscBool isseq; 431 432 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 433 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 434 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 435 } 436 PetscFunctionReturn(0); 437 } 438 439 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 440 { 441 DM dm; 442 MPI_Comm comm; 443 PetscViewerFormat format; 444 Vec v; 445 PetscBool isvtk, ishdf5; 446 PetscErrorCode ierr; 447 448 PetscFunctionBegin; 449 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 450 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 451 PetscCheckFalse(!dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 452 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 453 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 454 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 455 if (format == PETSC_VIEWER_NATIVE) { 456 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 457 /* this need a better fix */ 458 if (dm->useNatural) { 459 if (dm->sfNatural) { 460 const char *vecname; 461 PetscInt n, nroots; 462 463 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 464 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 465 if (n == nroots) { 466 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 467 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 468 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 469 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 470 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 471 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 472 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 473 } else v = originalv; 474 } else v = originalv; 475 476 if (ishdf5) { 477 #if defined(PETSC_HAVE_HDF5) 478 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 479 #else 480 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 481 #endif 482 } else if (isvtk) { 483 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 484 } else { 485 PetscBool isseq; 486 487 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 488 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 489 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 490 } 491 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 492 PetscFunctionReturn(0); 493 } 494 495 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 496 { 497 DM dm; 498 PetscBool ishdf5; 499 PetscErrorCode ierr; 500 501 PetscFunctionBegin; 502 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 503 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 504 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 505 if (ishdf5) { 506 DM dmBC; 507 Vec gv; 508 const char *name; 509 510 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 511 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 512 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 513 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 514 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 515 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 516 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 517 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 518 } else { 519 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 520 } 521 PetscFunctionReturn(0); 522 } 523 524 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 525 { 526 DM dm; 527 PetscBool ishdf5,isexodusii; 528 PetscErrorCode ierr; 529 530 PetscFunctionBegin; 531 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 532 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 533 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 534 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 535 if (ishdf5) { 536 #if defined(PETSC_HAVE_HDF5) 537 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 538 #else 539 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 540 #endif 541 } else if (isexodusii) { 542 #if defined(PETSC_HAVE_EXODUSII) 543 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 544 #else 545 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 546 #endif 547 } else { 548 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 549 } 550 PetscFunctionReturn(0); 551 } 552 553 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 554 { 555 DM dm; 556 PetscViewerFormat format; 557 PetscBool ishdf5; 558 PetscErrorCode ierr; 559 560 PetscFunctionBegin; 561 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 562 PetscCheckFalse(!dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 563 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 564 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 565 if (format == PETSC_VIEWER_NATIVE) { 566 if (dm->useNatural) { 567 if (dm->sfNatural) { 568 if (ishdf5) { 569 #if defined(PETSC_HAVE_HDF5) 570 Vec v; 571 const char *vecname; 572 573 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 574 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 575 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 576 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 577 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 578 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 579 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 580 #else 581 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 582 #endif 583 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 584 } 585 } else { 586 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 587 } 588 } 589 PetscFunctionReturn(0); 590 } 591 592 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 593 { 594 PetscSection coordSection; 595 Vec coordinates; 596 DMLabel depthLabel, celltypeLabel; 597 const char *name[4]; 598 const PetscScalar *a; 599 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 600 PetscErrorCode ierr; 601 602 PetscFunctionBegin; 603 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 604 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 605 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 606 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 607 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 608 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 609 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 610 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 611 name[0] = "vertex"; 612 name[1] = "edge"; 613 name[dim-1] = "face"; 614 name[dim] = "cell"; 615 for (c = cStart; c < cEnd; ++c) { 616 PetscInt *closure = NULL; 617 PetscInt closureSize, cl, ct; 618 619 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 620 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 621 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 622 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 623 for (cl = 0; cl < closureSize*2; cl += 2) { 624 PetscInt point = closure[cl], depth, dof, off, d, p; 625 626 if ((point < pStart) || (point >= pEnd)) continue; 627 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 628 if (!dof) continue; 629 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 630 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 631 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 632 for (p = 0; p < dof/dim; ++p) { 633 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 634 for (d = 0; d < dim; ++d) { 635 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 636 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 637 } 638 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 639 } 640 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 641 } 642 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 643 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 644 } 645 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 646 PetscFunctionReturn(0); 647 } 648 649 typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem; 650 const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 651 652 static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 653 { 654 PetscInt i; 655 PetscErrorCode ierr; 656 657 PetscFunctionBegin; 658 if (dim > 3) { 659 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]));CHKERRQ(ierr);} 660 } else { 661 PetscReal coords[3], trcoords[3]; 662 663 for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 664 switch (cs) { 665 case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break; 666 case CS_POLAR: 667 PetscCheckFalse(dim != 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %D", dim); 668 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 669 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 670 break; 671 case CS_CYLINDRICAL: 672 PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %D", dim); 673 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 674 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 675 trcoords[2] = coords[2]; 676 break; 677 case CS_SPHERICAL: 678 PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %D", dim); 679 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 680 trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 681 trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 682 break; 683 } 684 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]);CHKERRQ(ierr);} 685 } 686 PetscFunctionReturn(0); 687 } 688 689 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 690 { 691 DM_Plex *mesh = (DM_Plex*) dm->data; 692 DM cdm; 693 PetscSection coordSection; 694 Vec coordinates; 695 PetscViewerFormat format; 696 PetscErrorCode ierr; 697 698 PetscFunctionBegin; 699 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 700 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 701 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 702 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 703 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 704 const char *name; 705 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 706 PetscInt pStart, pEnd, p, numLabels, l; 707 PetscMPIInt rank, size; 708 709 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 710 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 711 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 712 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 713 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 714 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 715 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 716 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 717 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 718 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 719 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 720 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 721 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 722 for (p = pStart; p < pEnd; ++p) { 723 PetscInt dof, off, s; 724 725 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 726 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 727 for (s = off; s < off+dof; ++s) { 728 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 729 } 730 } 731 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 732 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 733 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 734 for (p = pStart; p < pEnd; ++p) { 735 PetscInt dof, off, c; 736 737 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 738 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 739 for (c = off; c < off+dof; ++c) { 740 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 741 } 742 } 743 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 744 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 745 if (coordSection && coordinates) { 746 CoordSystem cs = CS_CARTESIAN; 747 const PetscScalar *array; 748 PetscInt Nf, Nc, pStart, pEnd, p; 749 PetscMPIInt rank; 750 const char *name; 751 752 ierr = PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL);CHKERRQ(ierr); 753 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRMPI(ierr); 754 ierr = PetscSectionGetNumFields(coordSection, &Nf);CHKERRQ(ierr); 755 PetscCheckFalse(Nf != 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %D", Nf); 756 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 757 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 758 ierr = PetscObjectGetName((PetscObject) coordinates, &name);CHKERRQ(ierr); 759 ierr = PetscViewerASCIIPrintf(viewer, "%s with %D fields\n", name, Nf);CHKERRQ(ierr); 760 ierr = PetscViewerASCIIPrintf(viewer, " field 0 with %D components\n", Nc);CHKERRQ(ierr); 761 if (cs != CS_CARTESIAN) {ierr = PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs]);CHKERRQ(ierr);} 762 763 ierr = VecGetArrayRead(coordinates, &array);CHKERRQ(ierr); 764 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 765 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);CHKERRQ(ierr); 766 for (p = pStart; p < pEnd; ++p) { 767 PetscInt dof, off; 768 769 ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr); 770 ierr = PetscSectionGetOffset(coordSection, p, &off);CHKERRQ(ierr); 771 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " (%4D) dim %2D offset %3D", p, dof, off);CHKERRQ(ierr); 772 ierr = DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]);CHKERRQ(ierr); 773 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\n");CHKERRQ(ierr); 774 } 775 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 776 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 777 ierr = VecRestoreArrayRead(coordinates, &array);CHKERRQ(ierr); 778 } 779 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 780 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 781 for (l = 0; l < numLabels; ++l) { 782 DMLabel label; 783 PetscBool isdepth; 784 const char *name; 785 786 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 787 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 788 if (isdepth) continue; 789 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 790 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 791 } 792 if (size > 1) { 793 PetscSF sf; 794 795 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 796 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 797 } 798 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 799 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 800 const char *name, *color; 801 const char *defcolors[3] = {"gray", "orange", "green"}; 802 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 803 char lname[PETSC_MAX_PATH_LEN]; 804 PetscReal scale = 2.0; 805 PetscReal tikzscale = 1.0; 806 PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 807 double tcoords[3]; 808 PetscScalar *coords; 809 PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 810 PetscMPIInt rank, size; 811 char **names, **colors, **lcolors; 812 PetscBool flg, lflg; 813 PetscBT wp = NULL; 814 PetscInt pEnd, pStart; 815 816 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 817 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 818 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 819 numLabels = PetscMax(numLabels, 10); 820 numColors = 10; 821 numLColors = 10; 822 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 823 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 824 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 825 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 826 for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 827 for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 828 n = 4; 829 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg);CHKERRQ(ierr); 830 PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 831 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg);CHKERRQ(ierr); 832 PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 833 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 834 if (!useLabels) numLabels = 0; 835 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 836 if (!useColors) { 837 numColors = 3; 838 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 839 } 840 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 841 if (!useColors) { 842 numLColors = 4; 843 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 844 } 845 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 846 plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 847 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 848 PetscCheckFalse(flg && plotEdges && depth < dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 849 if (depth < dim) plotEdges = PETSC_FALSE; 850 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL);CHKERRQ(ierr); 851 852 /* filter points with labelvalue != labeldefaultvalue */ 853 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 854 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 855 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 856 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 857 if (lflg) { 858 DMLabel lbl; 859 860 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 861 if (lbl) { 862 PetscInt val, defval; 863 864 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 865 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 866 for (c = pStart; c < pEnd; c++) { 867 PetscInt *closure = NULL; 868 PetscInt closureSize; 869 870 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 871 if (val == defval) continue; 872 873 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 874 for (p = 0; p < closureSize*2; p += 2) { 875 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 876 } 877 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 878 } 879 } 880 } 881 882 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 883 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 884 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 885 ierr = PetscViewerASCIIPrintf(viewer, "\ 886 \\documentclass[tikz]{standalone}\n\n\ 887 \\usepackage{pgflibraryshapes}\n\ 888 \\usetikzlibrary{backgrounds}\n\ 889 \\usetikzlibrary{arrows}\n\ 890 \\begin{document}\n");CHKERRQ(ierr); 891 if (size > 1) { 892 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 893 for (p = 0; p < size; ++p) { 894 if (p > 0 && p == size-1) { 895 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 896 } else if (p > 0) { 897 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 898 } 899 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 900 } 901 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 902 } 903 if (drawHasse) { 904 PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 905 906 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart);CHKERRQ(ierr); 907 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1);CHKERRQ(ierr); 908 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart);CHKERRQ(ierr); 909 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.);CHKERRQ(ierr); 910 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart);CHKERRQ(ierr); 911 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1);CHKERRQ(ierr); 912 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.);CHKERRQ(ierr); 913 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart);CHKERRQ(ierr); 914 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart);CHKERRQ(ierr); 915 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1);CHKERRQ(ierr); 916 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart);CHKERRQ(ierr); 917 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.);CHKERRQ(ierr); 918 } 919 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 920 921 /* Plot vertices */ 922 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 923 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 924 for (v = vStart; v < vEnd; ++v) { 925 PetscInt off, dof, d; 926 PetscBool isLabeled = PETSC_FALSE; 927 928 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 929 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 930 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 931 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 932 PetscCheckFalse(dof > 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 933 for (d = 0; d < dof; ++d) { 934 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 935 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 936 } 937 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 938 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 939 for (d = 0; d < dof; ++d) { 940 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 941 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 942 } 943 if (drawHasse) color = colors[0%numColors]; 944 else color = colors[rank%numColors]; 945 for (l = 0; l < numLabels; ++l) { 946 PetscInt val; 947 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 948 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 949 } 950 if (drawNumbers[0]) { 951 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 952 } else if (drawColors[0]) { 953 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 954 } else { 955 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank);CHKERRQ(ierr); 956 } 957 } 958 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 959 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 960 /* Plot edges */ 961 if (plotEdges) { 962 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 963 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 964 for (e = eStart; e < eEnd; ++e) { 965 const PetscInt *cone; 966 PetscInt coneSize, offA, offB, dof, d; 967 968 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 969 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 970 PetscCheckFalse(coneSize != 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 971 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 972 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 973 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 974 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 975 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 976 for (d = 0; d < dof; ++d) { 977 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 978 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 979 } 980 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 981 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 982 for (d = 0; d < dof; ++d) { 983 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 984 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 985 } 986 if (drawHasse) color = colors[1%numColors]; 987 else color = colors[rank%numColors]; 988 for (l = 0; l < numLabels; ++l) { 989 PetscInt val; 990 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 991 if (val >= 0) {color = lcolors[l%numLColors]; break;} 992 } 993 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 994 } 995 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 996 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 997 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 998 } 999 /* Plot cells */ 1000 if (dim == 3 || !drawNumbers[1]) { 1001 for (e = eStart; e < eEnd; ++e) { 1002 const PetscInt *cone; 1003 1004 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1005 color = colors[rank%numColors]; 1006 for (l = 0; l < numLabels; ++l) { 1007 PetscInt val; 1008 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 1009 if (val >= 0) {color = lcolors[l%numLColors]; break;} 1010 } 1011 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 1012 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 1013 } 1014 } else { 1015 DMPolytopeType ct; 1016 1017 /* Drawing a 2D polygon */ 1018 for (c = cStart; c < cEnd; ++c) { 1019 if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1020 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 1021 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 1022 ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 1023 ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1024 const PetscInt *cone; 1025 PetscInt coneSize, e; 1026 1027 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 1028 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 1029 for (e = 0; e < coneSize; ++e) { 1030 const PetscInt *econe; 1031 1032 ierr = DMPlexGetCone(dm, cone[e], &econe);CHKERRQ(ierr); 1033 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d) -- (%D_%d);\n", colors[rank%numColors], econe[0], rank, cone[e], rank, econe[1], rank);CHKERRQ(ierr); 1034 } 1035 } else { 1036 PetscInt *closure = NULL; 1037 PetscInt closureSize, Nv = 0, v; 1038 1039 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1040 for (p = 0; p < closureSize*2; p += 2) { 1041 const PetscInt point = closure[p]; 1042 1043 if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1044 } 1045 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 1046 for (v = 0; v <= Nv; ++v) { 1047 const PetscInt vertex = closure[v%Nv]; 1048 1049 if (v > 0) { 1050 if (plotEdges) { 1051 const PetscInt *edge; 1052 PetscInt endpoints[2], ne; 1053 1054 endpoints[0] = closure[v-1]; endpoints[1] = vertex; 1055 ierr = DMPlexGetJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1056 PetscCheckFalse(ne != 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]); 1057 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank);CHKERRQ(ierr); 1058 ierr = DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1059 } else { 1060 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr); 1061 } 1062 } 1063 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank);CHKERRQ(ierr); 1064 } 1065 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ";\n");CHKERRQ(ierr); 1066 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1067 } 1068 } 1069 } 1070 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1071 for (c = cStart; c < cEnd; ++c) { 1072 double ccoords[3] = {0.0, 0.0, 0.0}; 1073 PetscBool isLabeled = PETSC_FALSE; 1074 PetscInt *closure = NULL; 1075 PetscInt closureSize, dof, d, n = 0; 1076 1077 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 1078 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1079 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 1080 for (p = 0; p < closureSize*2; p += 2) { 1081 const PetscInt point = closure[p]; 1082 PetscInt off; 1083 1084 if ((point < vStart) || (point >= vEnd)) continue; 1085 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 1086 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 1087 for (d = 0; d < dof; ++d) { 1088 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1089 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1090 } 1091 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1092 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1093 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1094 ++n; 1095 } 1096 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 1097 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1098 for (d = 0; d < dof; ++d) { 1099 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 1100 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 1101 } 1102 if (drawHasse) color = colors[depth%numColors]; 1103 else color = colors[rank%numColors]; 1104 for (l = 0; l < numLabels; ++l) { 1105 PetscInt val; 1106 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 1107 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1108 } 1109 if (drawNumbers[dim]) { 1110 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 1111 } else if (drawColors[dim]) { 1112 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 1113 } else { 1114 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank);CHKERRQ(ierr); 1115 } 1116 } 1117 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1118 if (drawHasse) { 1119 color = colors[depth%numColors]; 1120 ierr = PetscViewerASCIIPrintf(viewer, "%% Cells\n");CHKERRQ(ierr); 1121 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n");CHKERRQ(ierr); 1122 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1123 ierr = PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color);CHKERRQ(ierr); 1124 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1125 1126 color = colors[1%numColors]; 1127 ierr = PetscViewerASCIIPrintf(viewer, "%% Edges\n");CHKERRQ(ierr); 1128 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n");CHKERRQ(ierr); 1129 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1130 ierr = PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color);CHKERRQ(ierr); 1131 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1132 1133 color = colors[0%numColors]; 1134 ierr = PetscViewerASCIIPrintf(viewer, "%% Vertices\n");CHKERRQ(ierr); 1135 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n");CHKERRQ(ierr); 1136 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1137 ierr = PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color);CHKERRQ(ierr); 1138 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1139 1140 for (p = pStart; p < pEnd; ++p) { 1141 const PetscInt *cone; 1142 PetscInt coneSize, cp; 1143 1144 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1145 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1146 for (cp = 0; cp < coneSize; ++cp) { 1147 ierr = PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank);CHKERRQ(ierr); 1148 } 1149 } 1150 } 1151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1152 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 1153 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 1154 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 1155 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 1156 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 1157 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 1158 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 1159 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 1160 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 1161 Vec cown,acown; 1162 VecScatter sct; 1163 ISLocalToGlobalMapping g2l; 1164 IS gid,acis; 1165 MPI_Comm comm,ncomm = MPI_COMM_NULL; 1166 MPI_Group ggroup,ngroup; 1167 PetscScalar *array,nid; 1168 const PetscInt *idxs; 1169 PetscInt *idxs2,*start,*adjacency,*work; 1170 PetscInt64 lm[3],gm[3]; 1171 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 1172 PetscMPIInt d1,d2,rank; 1173 1174 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1175 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1176 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1177 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1178 #endif 1179 if (ncomm != MPI_COMM_NULL) { 1180 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1181 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1182 d1 = 0; 1183 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1184 nid = d2; 1185 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1186 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1187 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1188 } else nid = 0.0; 1189 1190 /* Get connectivity */ 1191 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1192 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1193 1194 /* filter overlapped local cells */ 1195 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1196 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1197 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1198 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1199 for (c = cStart, cum = 0; c < cEnd; c++) { 1200 if (idxs[c-cStart] < 0) continue; 1201 idxs2[cum++] = idxs[c-cStart]; 1202 } 1203 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1204 PetscCheckFalse(numVertices != cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1205 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1206 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1207 1208 /* support for node-aware cell locality */ 1209 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1210 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1211 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1212 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1213 for (c = 0; c < numVertices; c++) array[c] = nid; 1214 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1215 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1216 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1217 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1218 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1219 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1220 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1221 1222 /* compute edgeCut */ 1223 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1224 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1225 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1226 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1227 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1228 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1229 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1230 PetscInt totl; 1231 1232 totl = start[c+1]-start[c]; 1233 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1234 for (i = 0; i < totl; i++) { 1235 if (work[i] < 0) { 1236 ect += 1; 1237 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1238 } 1239 } 1240 } 1241 ierr = PetscFree(work);CHKERRQ(ierr); 1242 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1243 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1244 lm[1] = -numVertices; 1245 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1246 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1247 lm[0] = ect; /* edgeCut */ 1248 lm[1] = ectn; /* node-aware edgeCut */ 1249 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1250 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1251 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1252 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1253 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); 1254 #else 1255 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1256 #endif 1257 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1258 ierr = PetscFree(start);CHKERRQ(ierr); 1259 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1260 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1261 } else { 1262 const char *name; 1263 PetscInt *sizes, *hybsizes, *ghostsizes; 1264 PetscInt locDepth, depth, cellHeight, dim, d; 1265 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1266 PetscInt numLabels, l, maxSize = 17; 1267 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1268 MPI_Comm comm; 1269 PetscMPIInt size, rank; 1270 1271 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1272 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1273 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1274 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1275 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1276 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1277 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1278 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1279 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1280 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1281 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1282 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1283 gcNum = gcEnd - gcStart; 1284 if (size < maxSize) {ierr = PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes);CHKERRQ(ierr);} 1285 else {ierr = PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes);CHKERRQ(ierr);} 1286 for (d = 0; d <= depth; d++) { 1287 PetscInt Nc[2] = {0, 0}, ict; 1288 1289 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1290 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1291 ict = ct0; 1292 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1293 ct0 = (DMPolytopeType) ict; 1294 for (p = pStart; p < pEnd; ++p) { 1295 DMPolytopeType ct; 1296 1297 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1298 if (ct == ct0) ++Nc[0]; 1299 else ++Nc[1]; 1300 } 1301 if (size < maxSize) { 1302 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1303 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1304 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1305 ierr = PetscViewerASCIIPrintf(viewer, " Number of %D-cells per rank:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1306 for (p = 0; p < size; ++p) { 1307 if (rank == 0) { 1308 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1309 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1310 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1311 } 1312 } 1313 } else { 1314 PetscInt locMinMax[2]; 1315 1316 locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1]; 1317 ierr = PetscGlobalMinMaxInt(comm, locMinMax, sizes);CHKERRQ(ierr); 1318 locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1]; 1319 ierr = PetscGlobalMinMaxInt(comm, locMinMax, hybsizes);CHKERRQ(ierr); 1320 if (d == depth) { 1321 locMinMax[0] = gcNum; locMinMax[1] = gcNum; 1322 ierr = PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes);CHKERRQ(ierr); 1323 } 1324 ierr = PetscViewerASCIIPrintf(viewer, " Min/Max of %D-cells per rank:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1325 ierr = PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]);CHKERRQ(ierr); 1326 if (hybsizes[0] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]);CHKERRQ(ierr);} 1327 if (ghostsizes[0] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]);CHKERRQ(ierr);} 1328 } 1329 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1330 } 1331 ierr = PetscFree3(sizes, hybsizes, ghostsizes);CHKERRQ(ierr); 1332 { 1333 const PetscReal *maxCell; 1334 const PetscReal *L; 1335 const DMBoundaryType *bd; 1336 PetscBool per, localized; 1337 1338 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1339 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1340 if (per) { 1341 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1342 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1343 for (d = 0; d < dim; ++d) { 1344 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1345 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1346 } 1347 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1348 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1349 } 1350 } 1351 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1352 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1353 for (l = 0; l < numLabels; ++l) { 1354 DMLabel label; 1355 const char *name; 1356 IS valueIS; 1357 const PetscInt *values; 1358 PetscInt numValues, v; 1359 1360 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1361 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1362 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1363 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1364 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1365 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1366 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1367 for (v = 0; v < numValues; ++v) { 1368 PetscInt size; 1369 1370 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1371 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1372 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1373 } 1374 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1375 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1376 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1377 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1378 } 1379 { 1380 char **labelNames; 1381 PetscInt Nl = numLabels; 1382 PetscBool flg; 1383 1384 ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr); 1385 ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr); 1386 for (l = 0; l < Nl; ++l) { 1387 DMLabel label; 1388 1389 ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr); 1390 if (flg) { 1391 ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr); 1392 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1393 } 1394 ierr = PetscFree(labelNames[l]);CHKERRQ(ierr); 1395 } 1396 ierr = PetscFree(labelNames);CHKERRQ(ierr); 1397 } 1398 /* If no fields are specified, people do not want to see adjacency */ 1399 if (dm->Nf) { 1400 PetscInt f; 1401 1402 for (f = 0; f < dm->Nf; ++f) { 1403 const char *name; 1404 1405 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1406 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1407 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1408 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1409 if (dm->fields[f].adjacency[0]) { 1410 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1411 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1412 } else { 1413 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1414 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1415 } 1416 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1417 } 1418 } 1419 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1420 if (cdm) { 1421 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1422 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1423 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1424 } 1425 } 1426 PetscFunctionReturn(0); 1427 } 1428 1429 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1430 { 1431 DMPolytopeType ct; 1432 PetscMPIInt rank; 1433 PetscInt cdim; 1434 PetscErrorCode ierr; 1435 1436 PetscFunctionBegin; 1437 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1438 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1439 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 1440 switch (ct) { 1441 case DM_POLYTOPE_SEGMENT: 1442 case DM_POLYTOPE_POINT_PRISM_TENSOR: 1443 switch (cdim) { 1444 case 1: 1445 { 1446 const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1447 const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1448 1449 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1450 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1451 ierr = PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1452 } 1453 break; 1454 case 2: 1455 { 1456 const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1457 const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1458 const PetscReal l = 0.1/PetscSqrtReal(dx*dx + dy*dy); 1459 1460 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1461 ierr = PetscDrawLine(draw, PetscRealPart(coords[0])+l*dx, PetscRealPart(coords[1])+l*dy, PetscRealPart(coords[0])-l*dx, PetscRealPart(coords[1])-l*dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1462 ierr = PetscDrawLine(draw, PetscRealPart(coords[2])+l*dx, PetscRealPart(coords[3])+l*dy, PetscRealPart(coords[2])-l*dx, PetscRealPart(coords[3])-l*dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1463 } 1464 break; 1465 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %D", cdim); 1466 } 1467 break; 1468 case DM_POLYTOPE_TRIANGLE: 1469 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1470 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1471 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1472 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1473 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1474 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1475 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1476 break; 1477 case DM_POLYTOPE_QUADRILATERAL: 1478 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1479 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1480 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1481 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1482 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1483 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1484 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1485 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1486 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1487 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1488 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1489 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1490 break; 1491 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1492 } 1493 PetscFunctionReturn(0); 1494 } 1495 1496 static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1497 { 1498 DMPolytopeType ct; 1499 PetscReal centroid[2] = {0., 0.}; 1500 PetscMPIInt rank; 1501 PetscInt fillColor, v, e, d; 1502 PetscErrorCode ierr; 1503 1504 PetscFunctionBegin; 1505 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1506 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1507 fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1508 switch (ct) { 1509 case DM_POLYTOPE_TRIANGLE: 1510 { 1511 PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1512 1513 for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1514 for (e = 0; e < 3; ++e) { 1515 refCoords[0] = refVertices[e*2+0]; 1516 refCoords[1] = refVertices[e*2+1]; 1517 for (d = 1; d <= edgeDiv; ++d) { 1518 refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1519 refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1520 } 1521 ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1522 for (d = 0; d < edgeDiv; ++d) { 1523 ierr = PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], fillColor, fillColor, fillColor);CHKERRQ(ierr); 1524 ierr = PetscDrawLine(draw, edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], PETSC_DRAW_BLACK);CHKERRQ(ierr); 1525 } 1526 } 1527 } 1528 break; 1529 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1530 } 1531 PetscFunctionReturn(0); 1532 } 1533 1534 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1535 { 1536 PetscDraw draw; 1537 DM cdm; 1538 PetscSection coordSection; 1539 Vec coordinates; 1540 const PetscScalar *coords; 1541 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1542 PetscReal *refCoords, *edgeCoords; 1543 PetscBool isnull, drawAffine = PETSC_TRUE; 1544 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1545 PetscErrorCode ierr; 1546 1547 PetscFunctionBegin; 1548 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1549 PetscCheckFalse(dim > 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1550 ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1551 if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1552 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1553 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1554 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1555 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1556 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1557 1558 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1559 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1560 if (isnull) PetscFunctionReturn(0); 1561 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1562 1563 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1564 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1565 for (c = 0; c < N; c += dim) { 1566 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1567 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1568 } 1569 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1570 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1571 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1572 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1573 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1574 1575 for (c = cStart; c < cEnd; ++c) { 1576 PetscScalar *coords = NULL; 1577 PetscInt numCoords; 1578 1579 ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1580 if (drawAffine) { 1581 ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1582 } else { 1583 ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1584 } 1585 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1586 } 1587 if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1588 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1589 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1590 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1591 PetscFunctionReturn(0); 1592 } 1593 1594 #if defined(PETSC_HAVE_EXODUSII) 1595 #include <exodusII.h> 1596 #include <petscviewerexodusii.h> 1597 #endif 1598 1599 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1600 { 1601 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1602 char name[PETSC_MAX_PATH_LEN]; 1603 PetscErrorCode ierr; 1604 1605 PetscFunctionBegin; 1606 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1607 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1608 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1609 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1610 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1611 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1612 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1613 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1614 if (iascii) { 1615 PetscViewerFormat format; 1616 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1617 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1618 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1619 } else { 1620 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1621 } 1622 } else if (ishdf5) { 1623 #if defined(PETSC_HAVE_HDF5) 1624 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1625 #else 1626 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1627 #endif 1628 } else if (isvtk) { 1629 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1630 } else if (isdraw) { 1631 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1632 } else if (isglvis) { 1633 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1634 #if defined(PETSC_HAVE_EXODUSII) 1635 } else if (isexodus) { 1636 /* 1637 exodusII requires that all sets be part of exactly one cell set. 1638 If the dm does not have a "Cell Sets" label defined, we create one 1639 with ID 1, containig all cells. 1640 Note that if the Cell Sets label is defined but does not cover all cells, 1641 we may still have a problem. This should probably be checked here or in the viewer; 1642 */ 1643 PetscInt numCS; 1644 ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr); 1645 if (!numCS) { 1646 PetscInt cStart, cEnd, c; 1647 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1648 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1649 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1650 } 1651 ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr); 1652 #endif 1653 } else { 1654 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1655 } 1656 /* Optionally view the partition */ 1657 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1658 if (flg) { 1659 Vec ranks; 1660 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1661 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1662 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1663 } 1664 /* Optionally view a label */ 1665 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr); 1666 if (flg) { 1667 DMLabel label; 1668 Vec val; 1669 1670 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1671 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1672 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1673 ierr = VecView(val, viewer);CHKERRQ(ierr); 1674 ierr = VecDestroy(&val);CHKERRQ(ierr); 1675 } 1676 PetscFunctionReturn(0); 1677 } 1678 1679 /*@ 1680 DMPlexTopologyView - Saves a DMPlex topology into a file 1681 1682 Collective on DM 1683 1684 Input Parameters: 1685 + dm - The DM whose topology is to be saved 1686 - viewer - The PetscViewer for saving 1687 1688 Level: advanced 1689 1690 .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad() 1691 @*/ 1692 PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1693 { 1694 PetscBool ishdf5; 1695 PetscErrorCode ierr; 1696 1697 PetscFunctionBegin; 1698 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1699 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1700 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1701 ierr = PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0);CHKERRQ(ierr); 1702 if (ishdf5) { 1703 #if defined(PETSC_HAVE_HDF5) 1704 PetscViewerFormat format; 1705 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1706 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1707 IS globalPointNumbering; 1708 1709 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1710 ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1711 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1712 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1713 #else 1714 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1715 #endif 1716 } 1717 ierr = PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0);CHKERRQ(ierr); 1718 PetscFunctionReturn(0); 1719 } 1720 1721 /*@ 1722 DMPlexCoordinatesView - Saves DMPlex coordinates into a file 1723 1724 Collective on DM 1725 1726 Input Parameters: 1727 + dm - The DM whose coordinates are to be saved 1728 - viewer - The PetscViewer for saving 1729 1730 Level: advanced 1731 1732 .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 1733 @*/ 1734 PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1735 { 1736 PetscBool ishdf5; 1737 PetscErrorCode ierr; 1738 1739 PetscFunctionBegin; 1740 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1741 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1742 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1743 ierr = PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0);CHKERRQ(ierr); 1744 if (ishdf5) { 1745 #if defined(PETSC_HAVE_HDF5) 1746 PetscViewerFormat format; 1747 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1748 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1749 ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1750 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1751 #else 1752 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1753 #endif 1754 } 1755 ierr = PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0);CHKERRQ(ierr); 1756 PetscFunctionReturn(0); 1757 } 1758 1759 /*@ 1760 DMPlexLabelsView - Saves DMPlex labels into a file 1761 1762 Collective on DM 1763 1764 Input Parameters: 1765 + dm - The DM whose labels are to be saved 1766 - viewer - The PetscViewer for saving 1767 1768 Level: advanced 1769 1770 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1771 @*/ 1772 PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1773 { 1774 PetscBool ishdf5; 1775 PetscErrorCode ierr; 1776 1777 PetscFunctionBegin; 1778 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1779 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1780 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1781 ierr = PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0);CHKERRQ(ierr); 1782 if (ishdf5) { 1783 #if defined(PETSC_HAVE_HDF5) 1784 IS globalPointNumbering; 1785 PetscViewerFormat format; 1786 1787 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1788 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1789 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1790 ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1791 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1792 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1793 #else 1794 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1795 #endif 1796 } 1797 ierr = PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0);CHKERRQ(ierr); 1798 PetscFunctionReturn(0); 1799 } 1800 1801 /*@ 1802 DMPlexSectionView - Saves a section associated with a DMPlex 1803 1804 Collective on DM 1805 1806 Input Parameters: 1807 + dm - The DM that contains the topology on which the section to be saved is defined 1808 . viewer - The PetscViewer for saving 1809 - sectiondm - The DM that contains the section to be saved 1810 1811 Level: advanced 1812 1813 Notes: 1814 This function is a wrapper around PetscSectionView(); in addition to the raw section, it saves information that associates the section points to the topology (dm) points. When the topology (dm) and the section are later loaded with DMPlexTopologyLoad() and DMPlexSectionLoad(), respectively, this information is used to match section points with topology points. 1815 1816 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1817 1818 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1819 @*/ 1820 PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1821 { 1822 PetscBool ishdf5; 1823 PetscErrorCode ierr; 1824 1825 PetscFunctionBegin; 1826 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1827 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1828 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1829 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1830 ierr = PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0);CHKERRQ(ierr); 1831 if (ishdf5) { 1832 #if defined(PETSC_HAVE_HDF5) 1833 ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr); 1834 #else 1835 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1836 #endif 1837 } 1838 ierr = PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0);CHKERRQ(ierr); 1839 PetscFunctionReturn(0); 1840 } 1841 1842 /*@ 1843 DMPlexGlobalVectorView - Saves a global vector 1844 1845 Collective on DM 1846 1847 Input Parameters: 1848 + dm - The DM that represents the topology 1849 . viewer - The PetscViewer to save data with 1850 . sectiondm - The DM that contains the global section on which vec is defined 1851 - vec - The global vector to be saved 1852 1853 Level: advanced 1854 1855 Notes: 1856 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1857 1858 Typical calling sequence 1859 $ DMCreate(PETSC_COMM_WORLD, &dm); 1860 $ DMSetType(dm, DMPLEX); 1861 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1862 $ DMClone(dm, §iondm); 1863 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1864 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1865 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1866 $ PetscSectionSetChart(section, pStart, pEnd); 1867 $ PetscSectionSetUp(section); 1868 $ DMSetLocalSection(sectiondm, section); 1869 $ PetscSectionDestroy(§ion); 1870 $ DMGetGlobalVector(sectiondm, &vec); 1871 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1872 $ DMPlexTopologyView(dm, viewer); 1873 $ DMPlexSectionView(dm, viewer, sectiondm); 1874 $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 1875 $ DMRestoreGlobalVector(sectiondm, &vec); 1876 $ DMDestroy(§iondm); 1877 $ DMDestroy(&dm); 1878 1879 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1880 @*/ 1881 PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1882 { 1883 PetscBool ishdf5; 1884 PetscErrorCode ierr; 1885 1886 PetscFunctionBegin; 1887 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1888 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1889 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1890 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1891 /* Check consistency */ 1892 { 1893 PetscSection section; 1894 PetscBool includesConstraints; 1895 PetscInt m, m1; 1896 1897 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1898 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 1899 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1900 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1901 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1902 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 1903 } 1904 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1905 ierr = PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0);CHKERRQ(ierr); 1906 if (ishdf5) { 1907 #if defined(PETSC_HAVE_HDF5) 1908 ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1909 #else 1910 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1911 #endif 1912 } 1913 ierr = PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0);CHKERRQ(ierr); 1914 PetscFunctionReturn(0); 1915 } 1916 1917 /*@ 1918 DMPlexLocalVectorView - Saves a local vector 1919 1920 Collective on DM 1921 1922 Input Parameters: 1923 + dm - The DM that represents the topology 1924 . viewer - The PetscViewer to save data with 1925 . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 1926 - vec - The local vector to be saved 1927 1928 Level: advanced 1929 1930 Notes: 1931 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1932 1933 Typical calling sequence 1934 $ DMCreate(PETSC_COMM_WORLD, &dm); 1935 $ DMSetType(dm, DMPLEX); 1936 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1937 $ DMClone(dm, §iondm); 1938 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1939 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1940 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1941 $ PetscSectionSetChart(section, pStart, pEnd); 1942 $ PetscSectionSetUp(section); 1943 $ DMSetLocalSection(sectiondm, section); 1944 $ DMGetLocalVector(sectiondm, &vec); 1945 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1946 $ DMPlexTopologyView(dm, viewer); 1947 $ DMPlexSectionView(dm, viewer, sectiondm); 1948 $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 1949 $ DMRestoreLocalVector(sectiondm, &vec); 1950 $ DMDestroy(§iondm); 1951 $ DMDestroy(&dm); 1952 1953 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1954 @*/ 1955 PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1956 { 1957 PetscBool ishdf5; 1958 PetscErrorCode ierr; 1959 1960 PetscFunctionBegin; 1961 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1962 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1963 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1964 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1965 /* Check consistency */ 1966 { 1967 PetscSection section; 1968 PetscBool includesConstraints; 1969 PetscInt m, m1; 1970 1971 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1972 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 1973 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1974 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1975 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1976 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 1977 } 1978 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1979 ierr = PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0);CHKERRQ(ierr); 1980 if (ishdf5) { 1981 #if defined(PETSC_HAVE_HDF5) 1982 ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1983 #else 1984 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1985 #endif 1986 } 1987 ierr = PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0);CHKERRQ(ierr); 1988 PetscFunctionReturn(0); 1989 } 1990 1991 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1992 { 1993 PetscBool ishdf5; 1994 PetscErrorCode ierr; 1995 1996 PetscFunctionBegin; 1997 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1998 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1999 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2000 if (ishdf5) { 2001 #if defined(PETSC_HAVE_HDF5) 2002 PetscViewerFormat format; 2003 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2004 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 2005 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 2006 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2007 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 2008 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2009 PetscFunctionReturn(0); 2010 #else 2011 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2012 #endif 2013 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2014 } 2015 2016 /*@ 2017 DMPlexTopologyLoad - Loads a topology into a DMPlex 2018 2019 Collective on DM 2020 2021 Input Parameters: 2022 + dm - The DM into which the topology is loaded 2023 - viewer - The PetscViewer for the saved topology 2024 2025 Output Parameters: 2026 . globalToLocalPointSF - The PetscSF that pushes points in [0, N) to the associated points in the loaded plex, where N is the global number of points; NULL if unneeded 2027 2028 Level: advanced 2029 2030 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2031 @*/ 2032 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2033 { 2034 PetscBool ishdf5; 2035 PetscErrorCode ierr; 2036 2037 PetscFunctionBegin; 2038 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2039 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2040 if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 2041 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2042 ierr = PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0);CHKERRQ(ierr); 2043 if (ishdf5) { 2044 #if defined(PETSC_HAVE_HDF5) 2045 PetscViewerFormat format; 2046 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2047 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2048 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2049 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2050 #else 2051 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2052 #endif 2053 } 2054 ierr = PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0);CHKERRQ(ierr); 2055 PetscFunctionReturn(0); 2056 } 2057 2058 /*@ 2059 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 2060 2061 Collective on DM 2062 2063 Input Parameters: 2064 + dm - The DM into which the coordinates are loaded 2065 . viewer - The PetscViewer for the saved coordinates 2066 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2067 2068 Level: advanced 2069 2070 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2071 @*/ 2072 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2073 { 2074 PetscBool ishdf5; 2075 PetscErrorCode ierr; 2076 2077 PetscFunctionBegin; 2078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2079 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2080 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 2081 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2082 ierr = PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0);CHKERRQ(ierr); 2083 if (ishdf5) { 2084 #if defined(PETSC_HAVE_HDF5) 2085 PetscViewerFormat format; 2086 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2087 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2088 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2089 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2090 #else 2091 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2092 #endif 2093 } 2094 ierr = PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0);CHKERRQ(ierr); 2095 PetscFunctionReturn(0); 2096 } 2097 2098 /*@ 2099 DMPlexLabelsLoad - Loads labels into a DMPlex 2100 2101 Collective on DM 2102 2103 Input Parameters: 2104 + dm - The DM into which the labels are loaded 2105 . viewer - The PetscViewer for the saved labels 2106 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2107 2108 Level: advanced 2109 2110 Notes: 2111 The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs. 2112 2113 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2114 @*/ 2115 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2116 { 2117 PetscBool ishdf5; 2118 PetscErrorCode ierr; 2119 2120 PetscFunctionBegin; 2121 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2122 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2123 if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 2124 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2125 ierr = PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0);CHKERRQ(ierr); 2126 if (ishdf5) { 2127 #if defined(PETSC_HAVE_HDF5) 2128 PetscViewerFormat format; 2129 2130 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2131 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2132 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2133 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2134 #else 2135 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2136 #endif 2137 } 2138 ierr = PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0);CHKERRQ(ierr); 2139 PetscFunctionReturn(0); 2140 } 2141 2142 /*@ 2143 DMPlexSectionLoad - Loads section into a DMPlex 2144 2145 Collective on DM 2146 2147 Input Parameters: 2148 + dm - The DM that represents the topology 2149 . viewer - The PetscViewer that represents the on-disk section (sectionA) 2150 . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2151 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2152 2153 Output Parameters 2154 + globalDofSF - The SF that migrates any on-disk Vec data associated with sectionA into a global Vec associated with the sectiondm's global section (NULL if not needed) 2155 - localDofSF - The SF that migrates any on-disk Vec data associated with sectionA into a local Vec associated with the sectiondm's local section (NULL if not needed) 2156 2157 Level: advanced 2158 2159 Notes: 2160 This function is a wrapper around PetscSectionLoad(); it loads, in addition to the raw section, a list of global point numbers that associates each on-disk section point with a global point number in [0, NX), where NX is the number of topology points in dm. Noting that globalToLocalPointSF associates each topology point in dm with a global number in [0, NX), one can readily establish an association of the on-disk section points with the topology points. 2161 2162 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2163 2164 The output parameter, globalDofSF (localDofSF), can later be used with DMPlexGlobalVectorLoad() (DMPlexLocalVectorLoad()) to load on-disk vectors into global (local) vectors associated with sectiondm's global (local) section. 2165 2166 Example using 2 processes: 2167 $ NX (number of points on dm): 4 2168 $ sectionA : the on-disk section 2169 $ vecA : a vector associated with sectionA 2170 $ sectionB : sectiondm's local section constructed in this function 2171 $ vecB (local) : a vector associated with sectiondm's local section 2172 $ vecB (global) : a vector associated with sectiondm's global section 2173 $ 2174 $ rank 0 rank 1 2175 $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2176 $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2177 $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2178 $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2179 $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2180 $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2181 $ sectionB->atlasDof : 1 0 1 | 1 3 2182 $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2183 $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2184 $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2185 $ 2186 $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2187 2188 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 2189 @*/ 2190 PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2191 { 2192 PetscBool ishdf5; 2193 PetscErrorCode ierr; 2194 2195 PetscFunctionBegin; 2196 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2197 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2198 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2199 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2200 if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2201 if (localDofSF) PetscValidPointer(localDofSF, 6); 2202 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2203 ierr = PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0);CHKERRQ(ierr); 2204 if (ishdf5) { 2205 #if defined(PETSC_HAVE_HDF5) 2206 ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr); 2207 #else 2208 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2209 #endif 2210 } 2211 ierr = PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0);CHKERRQ(ierr); 2212 PetscFunctionReturn(0); 2213 } 2214 2215 /*@ 2216 DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 2217 2218 Collective on DM 2219 2220 Input Parameters: 2221 + dm - The DM that represents the topology 2222 . viewer - The PetscViewer that represents the on-disk vector data 2223 . sectiondm - The DM that contains the global section on which vec is defined 2224 . sf - The SF that migrates the on-disk vector data into vec 2225 - vec - The global vector to set values of 2226 2227 Level: advanced 2228 2229 Notes: 2230 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2231 2232 Typical calling sequence 2233 $ DMCreate(PETSC_COMM_WORLD, &dm); 2234 $ DMSetType(dm, DMPLEX); 2235 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2236 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2237 $ DMClone(dm, §iondm); 2238 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2239 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2240 $ DMGetGlobalVector(sectiondm, &vec); 2241 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2242 $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2243 $ DMRestoreGlobalVector(sectiondm, &vec); 2244 $ PetscSFDestroy(&gsf); 2245 $ PetscSFDestroy(&sfX); 2246 $ DMDestroy(§iondm); 2247 $ DMDestroy(&dm); 2248 2249 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2250 @*/ 2251 PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2252 { 2253 PetscBool ishdf5; 2254 PetscErrorCode ierr; 2255 2256 PetscFunctionBegin; 2257 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2258 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2259 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2260 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2261 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2262 /* Check consistency */ 2263 { 2264 PetscSection section; 2265 PetscBool includesConstraints; 2266 PetscInt m, m1; 2267 2268 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2269 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 2270 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2271 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2272 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2273 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 2274 } 2275 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2276 ierr = PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2277 if (ishdf5) { 2278 #if defined(PETSC_HAVE_HDF5) 2279 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2280 #else 2281 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2282 #endif 2283 } 2284 ierr = PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2285 PetscFunctionReturn(0); 2286 } 2287 2288 /*@ 2289 DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 2290 2291 Collective on DM 2292 2293 Input Parameters: 2294 + dm - The DM that represents the topology 2295 . viewer - The PetscViewer that represents the on-disk vector data 2296 . sectiondm - The DM that contains the local section on which vec is defined 2297 . sf - The SF that migrates the on-disk vector data into vec 2298 - vec - The local vector to set values of 2299 2300 Level: advanced 2301 2302 Notes: 2303 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2304 2305 Typical calling sequence 2306 $ DMCreate(PETSC_COMM_WORLD, &dm); 2307 $ DMSetType(dm, DMPLEX); 2308 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2309 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2310 $ DMClone(dm, §iondm); 2311 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2312 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2313 $ DMGetLocalVector(sectiondm, &vec); 2314 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2315 $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2316 $ DMRestoreLocalVector(sectiondm, &vec); 2317 $ PetscSFDestroy(&lsf); 2318 $ PetscSFDestroy(&sfX); 2319 $ DMDestroy(§iondm); 2320 $ DMDestroy(&dm); 2321 2322 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2323 @*/ 2324 PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2325 { 2326 PetscBool ishdf5; 2327 PetscErrorCode ierr; 2328 2329 PetscFunctionBegin; 2330 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2331 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2332 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2333 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2334 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2335 /* Check consistency */ 2336 { 2337 PetscSection section; 2338 PetscBool includesConstraints; 2339 PetscInt m, m1; 2340 2341 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2342 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2343 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2344 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2345 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2346 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2347 } 2348 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2349 ierr = PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2350 if (ishdf5) { 2351 #if defined(PETSC_HAVE_HDF5) 2352 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2353 #else 2354 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2355 #endif 2356 } 2357 ierr = PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2358 PetscFunctionReturn(0); 2359 } 2360 2361 PetscErrorCode DMDestroy_Plex(DM dm) 2362 { 2363 DM_Plex *mesh = (DM_Plex*) dm->data; 2364 PetscErrorCode ierr; 2365 2366 PetscFunctionBegin; 2367 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 2368 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 2369 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 2370 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 2371 if (--mesh->refct > 0) PetscFunctionReturn(0); 2372 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 2373 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 2374 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 2375 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 2376 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 2377 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 2378 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 2379 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 2380 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 2381 ierr = PetscFree(mesh->transformType);CHKERRQ(ierr); 2382 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 2383 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 2384 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 2385 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 2386 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 2387 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 2388 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 2389 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 2390 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 2391 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 2392 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 2393 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 2394 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 2395 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 2396 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 2397 if (mesh->metricCtx) { ierr = PetscFree(mesh->metricCtx);CHKERRQ(ierr); } 2398 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2399 ierr = PetscFree(mesh);CHKERRQ(ierr); 2400 PetscFunctionReturn(0); 2401 } 2402 2403 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2404 { 2405 PetscSection sectionGlobal; 2406 PetscInt bs = -1, mbs; 2407 PetscInt localSize; 2408 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2409 PetscErrorCode ierr; 2410 MatType mtype; 2411 ISLocalToGlobalMapping ltog; 2412 2413 PetscFunctionBegin; 2414 ierr = MatInitializePackage();CHKERRQ(ierr); 2415 mtype = dm->mattype; 2416 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 2417 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 2418 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 2419 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 2420 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2421 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 2422 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2423 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 2424 if (mbs > 1) bs = mbs; 2425 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 2426 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 2427 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 2428 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 2429 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 2430 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 2431 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 2432 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 2433 if (!isShell) { 2434 PetscSection subSection; 2435 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2436 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 2437 PetscInt pStart, pEnd, p, dof, cdof; 2438 2439 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 2440 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 2441 PetscSection section; 2442 PetscInt size; 2443 2444 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 2445 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2446 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 2447 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 2448 } else { 2449 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2450 } 2451 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2452 for (p = pStart, lsize = 0; p < pEnd; ++p) { 2453 PetscInt bdof; 2454 2455 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2456 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2457 dof = dof < 0 ? -(dof+1) : dof; 2458 bdof = cdof && (dof-cdof) ? 1 : dof; 2459 if (dof) { 2460 if (bs < 0) {bs = bdof;} 2461 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 2462 } 2463 if (isMatIS) { 2464 PetscInt loff,c,off; 2465 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 2466 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 2467 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 2468 } 2469 } 2470 /* Must have same blocksize on all procs (some might have no points) */ 2471 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 2472 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2473 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 2474 else {bs = bsMinMax[0];} 2475 bs = PetscMax(1,bs); 2476 if (isMatIS) { /* Must reduce indices by blocksize */ 2477 PetscInt l; 2478 2479 lsize = lsize/bs; 2480 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 2481 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 2482 } 2483 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2484 if (isMatIS) { 2485 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 2486 } 2487 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2488 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2489 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2490 } 2491 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2492 PetscFunctionReturn(0); 2493 } 2494 2495 /*@ 2496 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2497 2498 Not collective 2499 2500 Input Parameter: 2501 . mesh - The DMPlex 2502 2503 Output Parameters: 2504 . subsection - The subdomain section 2505 2506 Level: developer 2507 2508 .seealso: 2509 @*/ 2510 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2511 { 2512 DM_Plex *mesh = (DM_Plex*) dm->data; 2513 PetscErrorCode ierr; 2514 2515 PetscFunctionBegin; 2516 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2517 if (!mesh->subdomainSection) { 2518 PetscSection section; 2519 PetscSF sf; 2520 2521 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2522 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2523 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2524 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2525 } 2526 *subsection = mesh->subdomainSection; 2527 PetscFunctionReturn(0); 2528 } 2529 2530 /*@ 2531 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2532 2533 Not collective 2534 2535 Input Parameter: 2536 . mesh - The DMPlex 2537 2538 Output Parameters: 2539 + pStart - The first mesh point 2540 - pEnd - The upper bound for mesh points 2541 2542 Level: beginner 2543 2544 .seealso: DMPlexCreate(), DMPlexSetChart() 2545 @*/ 2546 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2547 { 2548 DM_Plex *mesh = (DM_Plex*) dm->data; 2549 PetscErrorCode ierr; 2550 2551 PetscFunctionBegin; 2552 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2553 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2554 PetscFunctionReturn(0); 2555 } 2556 2557 /*@ 2558 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2559 2560 Not collective 2561 2562 Input Parameters: 2563 + mesh - The DMPlex 2564 . pStart - The first mesh point 2565 - pEnd - The upper bound for mesh points 2566 2567 Output Parameters: 2568 2569 Level: beginner 2570 2571 .seealso: DMPlexCreate(), DMPlexGetChart() 2572 @*/ 2573 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2574 { 2575 DM_Plex *mesh = (DM_Plex*) dm->data; 2576 PetscErrorCode ierr; 2577 2578 PetscFunctionBegin; 2579 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2580 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2581 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2582 PetscFunctionReturn(0); 2583 } 2584 2585 /*@ 2586 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2587 2588 Not collective 2589 2590 Input Parameters: 2591 + mesh - The DMPlex 2592 - p - The point, which must lie in the chart set with DMPlexSetChart() 2593 2594 Output Parameter: 2595 . size - The cone size for point p 2596 2597 Level: beginner 2598 2599 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2600 @*/ 2601 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2602 { 2603 DM_Plex *mesh = (DM_Plex*) dm->data; 2604 PetscErrorCode ierr; 2605 2606 PetscFunctionBegin; 2607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2608 PetscValidPointer(size, 3); 2609 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2610 PetscFunctionReturn(0); 2611 } 2612 2613 /*@ 2614 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2615 2616 Not collective 2617 2618 Input Parameters: 2619 + mesh - The DMPlex 2620 . p - The point, which must lie in the chart set with DMPlexSetChart() 2621 - size - The cone size for point p 2622 2623 Output Parameter: 2624 2625 Note: 2626 This should be called after DMPlexSetChart(). 2627 2628 Level: beginner 2629 2630 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2631 @*/ 2632 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2633 { 2634 DM_Plex *mesh = (DM_Plex*) dm->data; 2635 PetscErrorCode ierr; 2636 2637 PetscFunctionBegin; 2638 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2639 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2640 2641 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2642 PetscFunctionReturn(0); 2643 } 2644 2645 /*@ 2646 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2647 2648 Not collective 2649 2650 Input Parameters: 2651 + mesh - The DMPlex 2652 . p - The point, which must lie in the chart set with DMPlexSetChart() 2653 - size - The additional cone size for point p 2654 2655 Output Parameter: 2656 2657 Note: 2658 This should be called after DMPlexSetChart(). 2659 2660 Level: beginner 2661 2662 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2663 @*/ 2664 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2665 { 2666 DM_Plex *mesh = (DM_Plex*) dm->data; 2667 PetscInt csize; 2668 PetscErrorCode ierr; 2669 2670 PetscFunctionBegin; 2671 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2672 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2673 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2674 2675 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2676 PetscFunctionReturn(0); 2677 } 2678 2679 /*@C 2680 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2681 2682 Not collective 2683 2684 Input Parameters: 2685 + dm - The DMPlex 2686 - p - The point, which must lie in the chart set with DMPlexSetChart() 2687 2688 Output Parameter: 2689 . cone - An array of points which are on the in-edges for point p 2690 2691 Level: beginner 2692 2693 Fortran Notes: 2694 Since it returns an array, this routine is only available in Fortran 90, and you must 2695 include petsc.h90 in your code. 2696 You must also call DMPlexRestoreCone() after you finish using the returned array. 2697 DMPlexRestoreCone() is not needed/available in C. 2698 2699 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2700 @*/ 2701 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2702 { 2703 DM_Plex *mesh = (DM_Plex*) dm->data; 2704 PetscInt off; 2705 PetscErrorCode ierr; 2706 2707 PetscFunctionBegin; 2708 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2709 PetscValidPointer(cone, 3); 2710 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2711 *cone = &mesh->cones[off]; 2712 PetscFunctionReturn(0); 2713 } 2714 2715 /*@C 2716 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2717 2718 Not collective 2719 2720 Input Parameters: 2721 + dm - The DMPlex 2722 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2723 2724 Output Parameters: 2725 + pConesSection - PetscSection describing the layout of pCones 2726 - pCones - An array of points which are on the in-edges for the point set p 2727 2728 Level: intermediate 2729 2730 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2731 @*/ 2732 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2733 { 2734 PetscSection cs, newcs; 2735 PetscInt *cones; 2736 PetscInt *newarr=NULL; 2737 PetscInt n; 2738 PetscErrorCode ierr; 2739 2740 PetscFunctionBegin; 2741 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2742 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2743 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2744 if (pConesSection) *pConesSection = newcs; 2745 if (pCones) { 2746 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2747 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2748 } 2749 PetscFunctionReturn(0); 2750 } 2751 2752 /*@ 2753 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2754 2755 Not collective 2756 2757 Input Parameters: 2758 + dm - The DMPlex 2759 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2760 2761 Output Parameter: 2762 . expandedPoints - An array of vertices recursively expanded from input points 2763 2764 Level: advanced 2765 2766 Notes: 2767 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2768 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2769 2770 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2771 @*/ 2772 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2773 { 2774 IS *expandedPointsAll; 2775 PetscInt depth; 2776 PetscErrorCode ierr; 2777 2778 PetscFunctionBegin; 2779 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2780 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2781 PetscValidPointer(expandedPoints, 3); 2782 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2783 *expandedPoints = expandedPointsAll[0]; 2784 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2785 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2786 PetscFunctionReturn(0); 2787 } 2788 2789 /*@ 2790 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). 2791 2792 Not collective 2793 2794 Input Parameters: 2795 + dm - The DMPlex 2796 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2797 2798 Output Parameters: 2799 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2800 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2801 - sections - (optional) An array of sections which describe mappings from points to their cone points 2802 2803 Level: advanced 2804 2805 Notes: 2806 Like DMPlexGetConeTuple() but recursive. 2807 2808 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. 2809 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2810 2811 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: 2812 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2813 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2814 2815 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2816 @*/ 2817 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2818 { 2819 const PetscInt *arr0=NULL, *cone=NULL; 2820 PetscInt *arr=NULL, *newarr=NULL; 2821 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2822 IS *expandedPoints_; 2823 PetscSection *sections_; 2824 PetscErrorCode ierr; 2825 2826 PetscFunctionBegin; 2827 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2828 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2829 if (depth) PetscValidIntPointer(depth, 3); 2830 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2831 if (sections) PetscValidPointer(sections, 5); 2832 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2833 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2834 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2835 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2836 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2837 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2838 for (d=depth_-1; d>=0; d--) { 2839 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2840 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2841 for (i=0; i<n; i++) { 2842 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2843 if (arr[i] >= start && arr[i] < end) { 2844 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2845 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2846 } else { 2847 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2848 } 2849 } 2850 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2851 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2852 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2853 for (i=0; i<n; i++) { 2854 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2855 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2856 if (cn > 1) { 2857 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2858 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2859 } else { 2860 newarr[co] = arr[i]; 2861 } 2862 } 2863 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2864 arr = newarr; 2865 n = newn; 2866 } 2867 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2868 *depth = depth_; 2869 if (expandedPoints) *expandedPoints = expandedPoints_; 2870 else { 2871 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2872 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2873 } 2874 if (sections) *sections = sections_; 2875 else { 2876 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2877 ierr = PetscFree(sections_);CHKERRQ(ierr); 2878 } 2879 PetscFunctionReturn(0); 2880 } 2881 2882 /*@ 2883 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2884 2885 Not collective 2886 2887 Input Parameters: 2888 + dm - The DMPlex 2889 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2890 2891 Output Parameters: 2892 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2893 . expandedPoints - (optional) An array of recursively expanded cones 2894 - sections - (optional) An array of sections which describe mappings from points to their cone points 2895 2896 Level: advanced 2897 2898 Notes: 2899 See DMPlexGetConeRecursive() for details. 2900 2901 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2902 @*/ 2903 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2904 { 2905 PetscInt d, depth_; 2906 PetscErrorCode ierr; 2907 2908 PetscFunctionBegin; 2909 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2910 PetscCheckFalse(depth && *depth != depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2911 if (depth) *depth = 0; 2912 if (expandedPoints) { 2913 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2914 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2915 } 2916 if (sections) { 2917 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2918 ierr = PetscFree(*sections);CHKERRQ(ierr); 2919 } 2920 PetscFunctionReturn(0); 2921 } 2922 2923 /*@ 2924 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 2925 2926 Not collective 2927 2928 Input Parameters: 2929 + mesh - The DMPlex 2930 . p - The point, which must lie in the chart set with DMPlexSetChart() 2931 - cone - An array of points which are on the in-edges for point p 2932 2933 Output Parameter: 2934 2935 Note: 2936 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2937 2938 Level: beginner 2939 2940 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2941 @*/ 2942 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2943 { 2944 DM_Plex *mesh = (DM_Plex*) dm->data; 2945 PetscInt pStart, pEnd; 2946 PetscInt dof, off, c; 2947 PetscErrorCode ierr; 2948 2949 PetscFunctionBegin; 2950 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2951 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2952 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2953 if (dof) PetscValidPointer(cone, 3); 2954 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2955 PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 2956 for (c = 0; c < dof; ++c) { 2957 PetscCheckFalse((cone[c] < pStart) || (cone[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 2958 mesh->cones[off+c] = cone[c]; 2959 } 2960 PetscFunctionReturn(0); 2961 } 2962 2963 /*@C 2964 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2965 2966 Not collective 2967 2968 Input Parameters: 2969 + mesh - The DMPlex 2970 - p - The point, which must lie in the chart set with DMPlexSetChart() 2971 2972 Output Parameter: 2973 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2974 integer giving the prescription for cone traversal. 2975 2976 Level: beginner 2977 2978 Notes: 2979 The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 2980 the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 2981 of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 2982 with the identity. 2983 2984 Fortran Notes: 2985 Since it returns an array, this routine is only available in Fortran 90, and you must 2986 include petsc.h90 in your code. 2987 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2988 DMPlexRestoreConeOrientation() is not needed/available in C. 2989 2990 .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2991 @*/ 2992 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2993 { 2994 DM_Plex *mesh = (DM_Plex*) dm->data; 2995 PetscInt off; 2996 PetscErrorCode ierr; 2997 2998 PetscFunctionBegin; 2999 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3000 if (PetscDefined(USE_DEBUG)) { 3001 PetscInt dof; 3002 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3003 if (dof) PetscValidPointer(coneOrientation, 3); 3004 } 3005 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3006 3007 *coneOrientation = &mesh->coneOrientations[off]; 3008 PetscFunctionReturn(0); 3009 } 3010 3011 /*@ 3012 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3013 3014 Not collective 3015 3016 Input Parameters: 3017 + mesh - The DMPlex 3018 . p - The point, which must lie in the chart set with DMPlexSetChart() 3019 - coneOrientation - An array of orientations 3020 Output Parameter: 3021 3022 Notes: 3023 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3024 3025 The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 3026 3027 Level: beginner 3028 3029 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3030 @*/ 3031 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3032 { 3033 DM_Plex *mesh = (DM_Plex*) dm->data; 3034 PetscInt pStart, pEnd; 3035 PetscInt dof, off, c; 3036 PetscErrorCode ierr; 3037 3038 PetscFunctionBegin; 3039 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3040 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3041 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3042 if (dof) PetscValidPointer(coneOrientation, 3); 3043 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3044 PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3045 for (c = 0; c < dof; ++c) { 3046 PetscInt cdof, o = coneOrientation[c]; 3047 3048 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 3049 PetscCheckFalse(o && ((o < -(cdof+1)) || (o >= cdof)),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 3050 mesh->coneOrientations[off+c] = o; 3051 } 3052 PetscFunctionReturn(0); 3053 } 3054 3055 /*@ 3056 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 3057 3058 Not collective 3059 3060 Input Parameters: 3061 + mesh - The DMPlex 3062 . p - The point, which must lie in the chart set with DMPlexSetChart() 3063 . conePos - The local index in the cone where the point should be put 3064 - conePoint - The mesh point to insert 3065 3066 Level: beginner 3067 3068 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3069 @*/ 3070 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3071 { 3072 DM_Plex *mesh = (DM_Plex*) dm->data; 3073 PetscInt pStart, pEnd; 3074 PetscInt dof, off; 3075 PetscErrorCode ierr; 3076 3077 PetscFunctionBegin; 3078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3079 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3080 PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3081 PetscCheckFalse((conePoint < pStart) || (conePoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 3082 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3083 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3084 PetscCheckFalse((conePos < 0) || (conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 3085 mesh->cones[off+conePos] = conePoint; 3086 PetscFunctionReturn(0); 3087 } 3088 3089 /*@ 3090 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 3091 3092 Not collective 3093 3094 Input Parameters: 3095 + mesh - The DMPlex 3096 . p - The point, which must lie in the chart set with DMPlexSetChart() 3097 . conePos - The local index in the cone where the point should be put 3098 - coneOrientation - The point orientation to insert 3099 3100 Level: beginner 3101 3102 Notes: 3103 The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3104 3105 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3106 @*/ 3107 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3108 { 3109 DM_Plex *mesh = (DM_Plex*) dm->data; 3110 PetscInt pStart, pEnd; 3111 PetscInt dof, off; 3112 PetscErrorCode ierr; 3113 3114 PetscFunctionBegin; 3115 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3116 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3117 PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3118 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3119 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3120 PetscCheckFalse((conePos < 0) || (conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 3121 mesh->coneOrientations[off+conePos] = coneOrientation; 3122 PetscFunctionReturn(0); 3123 } 3124 3125 /*@ 3126 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3127 3128 Not collective 3129 3130 Input Parameters: 3131 + mesh - The DMPlex 3132 - p - The point, which must lie in the chart set with DMPlexSetChart() 3133 3134 Output Parameter: 3135 . size - The support size for point p 3136 3137 Level: beginner 3138 3139 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 3140 @*/ 3141 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3142 { 3143 DM_Plex *mesh = (DM_Plex*) dm->data; 3144 PetscErrorCode ierr; 3145 3146 PetscFunctionBegin; 3147 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3148 PetscValidPointer(size, 3); 3149 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3150 PetscFunctionReturn(0); 3151 } 3152 3153 /*@ 3154 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3155 3156 Not collective 3157 3158 Input Parameters: 3159 + mesh - The DMPlex 3160 . p - The point, which must lie in the chart set with DMPlexSetChart() 3161 - size - The support size for point p 3162 3163 Output Parameter: 3164 3165 Note: 3166 This should be called after DMPlexSetChart(). 3167 3168 Level: beginner 3169 3170 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 3171 @*/ 3172 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3173 { 3174 DM_Plex *mesh = (DM_Plex*) dm->data; 3175 PetscErrorCode ierr; 3176 3177 PetscFunctionBegin; 3178 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3179 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3180 3181 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 3182 PetscFunctionReturn(0); 3183 } 3184 3185 /*@C 3186 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3187 3188 Not collective 3189 3190 Input Parameters: 3191 + mesh - The DMPlex 3192 - p - The point, which must lie in the chart set with DMPlexSetChart() 3193 3194 Output Parameter: 3195 . support - An array of points which are on the out-edges for point p 3196 3197 Level: beginner 3198 3199 Fortran Notes: 3200 Since it returns an array, this routine is only available in Fortran 90, and you must 3201 include petsc.h90 in your code. 3202 You must also call DMPlexRestoreSupport() after you finish using the returned array. 3203 DMPlexRestoreSupport() is not needed/available in C. 3204 3205 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 3206 @*/ 3207 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3208 { 3209 DM_Plex *mesh = (DM_Plex*) dm->data; 3210 PetscInt off; 3211 PetscErrorCode ierr; 3212 3213 PetscFunctionBegin; 3214 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3215 PetscValidPointer(support, 3); 3216 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3217 *support = &mesh->supports[off]; 3218 PetscFunctionReturn(0); 3219 } 3220 3221 /*@ 3222 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3223 3224 Not collective 3225 3226 Input Parameters: 3227 + mesh - The DMPlex 3228 . p - The point, which must lie in the chart set with DMPlexSetChart() 3229 - support - An array of points which are on the out-edges for point p 3230 3231 Output Parameter: 3232 3233 Note: 3234 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3235 3236 Level: beginner 3237 3238 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 3239 @*/ 3240 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3241 { 3242 DM_Plex *mesh = (DM_Plex*) dm->data; 3243 PetscInt pStart, pEnd; 3244 PetscInt dof, off, c; 3245 PetscErrorCode ierr; 3246 3247 PetscFunctionBegin; 3248 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3249 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3250 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3251 if (dof) PetscValidPointer(support, 3); 3252 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3253 PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3254 for (c = 0; c < dof; ++c) { 3255 PetscCheckFalse((support[c] < pStart) || (support[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 3256 mesh->supports[off+c] = support[c]; 3257 } 3258 PetscFunctionReturn(0); 3259 } 3260 3261 /*@ 3262 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 3263 3264 Not collective 3265 3266 Input Parameters: 3267 + mesh - The DMPlex 3268 . p - The point, which must lie in the chart set with DMPlexSetChart() 3269 . supportPos - The local index in the cone where the point should be put 3270 - supportPoint - The mesh point to insert 3271 3272 Level: beginner 3273 3274 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3275 @*/ 3276 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3277 { 3278 DM_Plex *mesh = (DM_Plex*) dm->data; 3279 PetscInt pStart, pEnd; 3280 PetscInt dof, off; 3281 PetscErrorCode ierr; 3282 3283 PetscFunctionBegin; 3284 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3285 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3286 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3287 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3288 PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3289 PetscCheckFalse((supportPoint < pStart) || (supportPoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 3290 PetscCheckFalse(supportPos >= dof,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 3291 mesh->supports[off+supportPos] = supportPoint; 3292 PetscFunctionReturn(0); 3293 } 3294 3295 /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3296 PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3297 { 3298 switch (ct) { 3299 case DM_POLYTOPE_SEGMENT: 3300 if (o == -1) return -2; 3301 break; 3302 case DM_POLYTOPE_TRIANGLE: 3303 if (o == -3) return -1; 3304 if (o == -2) return -3; 3305 if (o == -1) return -2; 3306 break; 3307 case DM_POLYTOPE_QUADRILATERAL: 3308 if (o == -4) return -2; 3309 if (o == -3) return -1; 3310 if (o == -2) return -4; 3311 if (o == -1) return -3; 3312 break; 3313 default: return o; 3314 } 3315 return o; 3316 } 3317 3318 /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3319 PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3320 { 3321 switch (ct) { 3322 case DM_POLYTOPE_SEGMENT: 3323 if ((o == -2) || (o == 1)) return -1; 3324 if (o == -1) return 0; 3325 break; 3326 case DM_POLYTOPE_TRIANGLE: 3327 if (o == -3) return -2; 3328 if (o == -2) return -1; 3329 if (o == -1) return -3; 3330 break; 3331 case DM_POLYTOPE_QUADRILATERAL: 3332 if (o == -4) return -2; 3333 if (o == -3) return -1; 3334 if (o == -2) return -4; 3335 if (o == -1) return -3; 3336 break; 3337 default: return o; 3338 } 3339 return o; 3340 } 3341 3342 /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3343 PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3344 { 3345 PetscInt pStart, pEnd, p; 3346 PetscErrorCode ierr; 3347 3348 PetscFunctionBegin; 3349 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3350 for (p = pStart; p < pEnd; ++p) { 3351 const PetscInt *cone, *ornt; 3352 PetscInt coneSize, c; 3353 3354 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3355 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3356 ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr); 3357 for (c = 0; c < coneSize; ++c) { 3358 DMPolytopeType ct; 3359 const PetscInt o = ornt[c]; 3360 3361 ierr = DMPlexGetCellType(dm, cone[c], &ct);CHKERRQ(ierr); 3362 switch (ct) { 3363 case DM_POLYTOPE_SEGMENT: 3364 if ((o == -2) || (o == 1)) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3365 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, 0);CHKERRQ(ierr);} 3366 break; 3367 case DM_POLYTOPE_TRIANGLE: 3368 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3369 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3370 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3371 break; 3372 case DM_POLYTOPE_QUADRILATERAL: 3373 if (o == -4) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3374 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3375 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -4);CHKERRQ(ierr);} 3376 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3377 break; 3378 default: break; 3379 } 3380 } 3381 } 3382 PetscFunctionReturn(0); 3383 } 3384 3385 static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3386 { 3387 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3388 PetscInt *closure; 3389 const PetscInt *tmp = NULL, *tmpO = NULL; 3390 PetscInt off = 0, tmpSize, t; 3391 PetscErrorCode ierr; 3392 3393 PetscFunctionBeginHot; 3394 if (ornt) { 3395 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3396 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3397 } 3398 if (*points) { 3399 closure = *points; 3400 } else { 3401 PetscInt maxConeSize, maxSupportSize; 3402 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3403 ierr = DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure);CHKERRQ(ierr); 3404 } 3405 if (useCone) { 3406 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3407 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3408 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3409 } else { 3410 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3411 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3412 } 3413 if (ct == DM_POLYTOPE_UNKNOWN) { 3414 closure[off++] = p; 3415 closure[off++] = 0; 3416 for (t = 0; t < tmpSize; ++t) { 3417 closure[off++] = tmp[t]; 3418 closure[off++] = tmpO ? tmpO[t] : 0; 3419 } 3420 } else { 3421 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);CHKERRQ(ierr); 3422 3423 /* We assume that cells with a valid type have faces with a valid type */ 3424 closure[off++] = p; 3425 closure[off++] = ornt; 3426 for (t = 0; t < tmpSize; ++t) { 3427 DMPolytopeType ft; 3428 3429 ierr = DMPlexGetCellType(dm, tmp[t], &ft);CHKERRQ(ierr); 3430 closure[off++] = tmp[arr[t]]; 3431 closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3432 } 3433 } 3434 if (numPoints) *numPoints = tmpSize+1; 3435 if (points) *points = closure; 3436 PetscFunctionReturn(0); 3437 } 3438 3439 /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3440 static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3441 { 3442 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3443 const PetscInt *cone, *ornt; 3444 PetscInt *pts, *closure = NULL; 3445 DMPolytopeType ft; 3446 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3447 PetscInt dim, coneSize, c, d, clSize, cl; 3448 PetscErrorCode ierr; 3449 3450 PetscFunctionBeginHot; 3451 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3452 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 3453 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3454 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 3455 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3456 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3457 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3458 maxSize = PetscMax(coneSeries, supportSeries); 3459 if (*points) {pts = *points;} 3460 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts);CHKERRQ(ierr);} 3461 c = 0; 3462 pts[c++] = point; 3463 pts[c++] = o; 3464 ierr = DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft);CHKERRQ(ierr); 3465 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure);CHKERRQ(ierr); 3466 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3467 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure);CHKERRQ(ierr); 3468 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3469 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure);CHKERRQ(ierr); 3470 for (d = 2; d < coneSize; ++d) { 3471 ierr = DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft);CHKERRQ(ierr); 3472 pts[c++] = cone[arr[d*2+0]]; 3473 pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3474 } 3475 if (dim >= 3) { 3476 for (d = 2; d < coneSize; ++d) { 3477 const PetscInt fpoint = cone[arr[d*2+0]]; 3478 const PetscInt *fcone, *fornt; 3479 PetscInt fconeSize, fc, i; 3480 3481 ierr = DMPlexGetCellType(dm, fpoint, &ft);CHKERRQ(ierr); 3482 const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 3483 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 3484 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 3485 ierr = DMPlexGetConeOrientation(dm, fpoint, &fornt);CHKERRQ(ierr); 3486 for (fc = 0; fc < fconeSize; ++fc) { 3487 const PetscInt cp = fcone[farr[fc*2+0]]; 3488 const PetscInt co = farr[fc*2+1]; 3489 3490 for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3491 if (i == c) { 3492 ierr = DMPlexGetCellType(dm, cp, &ft);CHKERRQ(ierr); 3493 pts[c++] = cp; 3494 pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3495 } 3496 } 3497 } 3498 } 3499 *numPoints = c/2; 3500 *points = pts; 3501 PetscFunctionReturn(0); 3502 } 3503 3504 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3505 { 3506 DMPolytopeType ct; 3507 PetscInt *closure, *fifo; 3508 PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3509 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3510 PetscInt depth, maxSize; 3511 PetscErrorCode ierr; 3512 3513 PetscFunctionBeginHot; 3514 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3515 if (depth == 1) { 3516 ierr = DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3517 PetscFunctionReturn(0); 3518 } 3519 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3520 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3521 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 3522 ierr = DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3523 PetscFunctionReturn(0); 3524 } 3525 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3526 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3527 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3528 maxSize = PetscMax(coneSeries, supportSeries); 3529 ierr = DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3530 if (*points) {closure = *points;} 3531 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure);CHKERRQ(ierr);} 3532 closure[closureSize++] = p; 3533 closure[closureSize++] = ornt; 3534 fifo[fifoSize++] = p; 3535 fifo[fifoSize++] = ornt; 3536 fifo[fifoSize++] = ct; 3537 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3538 while (fifoSize - fifoStart) { 3539 const PetscInt q = fifo[fifoStart++]; 3540 const PetscInt o = fifo[fifoStart++]; 3541 const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3542 const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3543 const PetscInt *tmp, *tmpO; 3544 PetscInt tmpSize, t; 3545 3546 if (PetscDefined(USE_DEBUG)) { 3547 PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 3548 PetscCheckFalse(o && (o >= nO || o < -nO),PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %D not in [%D,%D) for %s %D", o, -nO, nO, DMPolytopeTypes[qt], q); 3549 } 3550 if (useCone) { 3551 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3552 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3553 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3554 } else { 3555 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3556 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3557 tmpO = NULL; 3558 } 3559 for (t = 0; t < tmpSize; ++t) { 3560 const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3561 const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3562 const PetscInt cp = tmp[ip]; 3563 ierr = DMPlexGetCellType(dm, cp, &ct);CHKERRQ(ierr); 3564 const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3565 PetscInt c; 3566 3567 /* Check for duplicate */ 3568 for (c = 0; c < closureSize; c += 2) { 3569 if (closure[c] == cp) break; 3570 } 3571 if (c == closureSize) { 3572 closure[closureSize++] = cp; 3573 closure[closureSize++] = co; 3574 fifo[fifoSize++] = cp; 3575 fifo[fifoSize++] = co; 3576 fifo[fifoSize++] = ct; 3577 } 3578 } 3579 } 3580 ierr = DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3581 if (numPoints) *numPoints = closureSize/2; 3582 if (points) *points = closure; 3583 PetscFunctionReturn(0); 3584 } 3585 3586 /*@C 3587 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3588 3589 Not collective 3590 3591 Input Parameters: 3592 + dm - The DMPlex 3593 . p - The mesh point 3594 - useCone - PETSC_TRUE for the closure, otherwise return the star 3595 3596 Input/Output Parameter: 3597 . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 3598 if NULL on input, internal storage will be returned, otherwise the provided array is used 3599 3600 Output Parameter: 3601 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3602 3603 Note: 3604 If using internal storage (points is NULL on input), each call overwrites the last output. 3605 3606 Fortran Notes: 3607 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3608 3609 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3610 3611 Level: beginner 3612 3613 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3614 @*/ 3615 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3616 { 3617 PetscErrorCode ierr; 3618 3619 PetscFunctionBeginHot; 3620 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3621 if (numPoints) PetscValidIntPointer(numPoints, 4); 3622 if (points) PetscValidPointer(points, 5); 3623 ierr = DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points);CHKERRQ(ierr); 3624 PetscFunctionReturn(0); 3625 } 3626 3627 /*@C 3628 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3629 3630 Not collective 3631 3632 Input Parameters: 3633 + dm - The DMPlex 3634 . p - The mesh point 3635 . useCone - PETSC_TRUE for the closure, otherwise return the star 3636 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3637 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3638 3639 Note: 3640 If not using internal storage (points is not NULL on input), this call is unnecessary 3641 3642 Fortran Notes: 3643 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3644 3645 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3646 3647 Level: beginner 3648 3649 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3650 @*/ 3651 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3652 { 3653 PetscErrorCode ierr; 3654 3655 PetscFunctionBeginHot; 3656 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3657 if (numPoints) *numPoints = 0; 3658 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3659 PetscFunctionReturn(0); 3660 } 3661 3662 /*@ 3663 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3664 3665 Not collective 3666 3667 Input Parameter: 3668 . mesh - The DMPlex 3669 3670 Output Parameters: 3671 + maxConeSize - The maximum number of in-edges 3672 - maxSupportSize - The maximum number of out-edges 3673 3674 Level: beginner 3675 3676 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3677 @*/ 3678 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3679 { 3680 DM_Plex *mesh = (DM_Plex*) dm->data; 3681 3682 PetscFunctionBegin; 3683 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3684 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3685 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3686 PetscFunctionReturn(0); 3687 } 3688 3689 PetscErrorCode DMSetUp_Plex(DM dm) 3690 { 3691 DM_Plex *mesh = (DM_Plex*) dm->data; 3692 PetscInt size; 3693 PetscErrorCode ierr; 3694 3695 PetscFunctionBegin; 3696 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3697 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3698 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3699 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3700 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3701 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3702 if (mesh->maxSupportSize) { 3703 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3704 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3705 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3706 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3707 } 3708 PetscFunctionReturn(0); 3709 } 3710 3711 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3712 { 3713 PetscErrorCode ierr; 3714 3715 PetscFunctionBegin; 3716 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3717 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3718 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3719 if (dm->useNatural && dm->sfMigration) { 3720 PetscSF sfMigrationInv,sfNatural; 3721 PetscSection section, sectionSeq; 3722 3723 (*subdm)->sfMigration = dm->sfMigration; 3724 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3725 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3726 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3727 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3728 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3729 3730 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3731 (*subdm)->sfNatural = sfNatural; 3732 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3733 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3734 } 3735 PetscFunctionReturn(0); 3736 } 3737 3738 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3739 { 3740 PetscErrorCode ierr; 3741 PetscInt i = 0; 3742 3743 PetscFunctionBegin; 3744 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3745 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3746 (*superdm)->useNatural = PETSC_FALSE; 3747 for (i = 0; i < len; i++) { 3748 if (dms[i]->useNatural && dms[i]->sfMigration) { 3749 PetscSF sfMigrationInv,sfNatural; 3750 PetscSection section, sectionSeq; 3751 3752 (*superdm)->sfMigration = dms[i]->sfMigration; 3753 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3754 (*superdm)->useNatural = PETSC_TRUE; 3755 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3756 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3757 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3758 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3759 3760 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3761 (*superdm)->sfNatural = sfNatural; 3762 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3763 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3764 break; 3765 } 3766 } 3767 PetscFunctionReturn(0); 3768 } 3769 3770 /*@ 3771 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3772 3773 Not collective 3774 3775 Input Parameter: 3776 . mesh - The DMPlex 3777 3778 Output Parameter: 3779 3780 Note: 3781 This should be called after all calls to DMPlexSetCone() 3782 3783 Level: beginner 3784 3785 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3786 @*/ 3787 PetscErrorCode DMPlexSymmetrize(DM dm) 3788 { 3789 DM_Plex *mesh = (DM_Plex*) dm->data; 3790 PetscInt *offsets; 3791 PetscInt supportSize; 3792 PetscInt pStart, pEnd, p; 3793 PetscErrorCode ierr; 3794 3795 PetscFunctionBegin; 3796 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3797 PetscCheckFalse(mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3798 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3799 /* Calculate support sizes */ 3800 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3801 for (p = pStart; p < pEnd; ++p) { 3802 PetscInt dof, off, c; 3803 3804 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3805 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3806 for (c = off; c < off+dof; ++c) { 3807 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3808 } 3809 } 3810 for (p = pStart; p < pEnd; ++p) { 3811 PetscInt dof; 3812 3813 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3814 3815 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3816 } 3817 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3818 /* Calculate supports */ 3819 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3820 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3821 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3822 for (p = pStart; p < pEnd; ++p) { 3823 PetscInt dof, off, c; 3824 3825 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3826 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3827 for (c = off; c < off+dof; ++c) { 3828 const PetscInt q = mesh->cones[c]; 3829 PetscInt offS; 3830 3831 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3832 3833 mesh->supports[offS+offsets[q]] = p; 3834 ++offsets[q]; 3835 } 3836 } 3837 ierr = PetscFree(offsets);CHKERRQ(ierr); 3838 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3839 PetscFunctionReturn(0); 3840 } 3841 3842 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3843 { 3844 IS stratumIS; 3845 PetscErrorCode ierr; 3846 3847 PetscFunctionBegin; 3848 if (pStart >= pEnd) PetscFunctionReturn(0); 3849 if (PetscDefined(USE_DEBUG)) { 3850 PetscInt qStart, qEnd, numLevels, level; 3851 PetscBool overlap = PETSC_FALSE; 3852 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3853 for (level = 0; level < numLevels; level++) { 3854 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3855 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3856 } 3857 PetscCheckFalse(overlap,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); 3858 } 3859 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3860 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3861 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3862 PetscFunctionReturn(0); 3863 } 3864 3865 /*@ 3866 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3867 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3868 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3869 the DAG. 3870 3871 Collective on dm 3872 3873 Input Parameter: 3874 . mesh - The DMPlex 3875 3876 Output Parameter: 3877 3878 Notes: 3879 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3880 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3881 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3882 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3883 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3884 3885 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3886 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3887 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 3888 to interpolate only that one (e0), so that 3889 $ cone(c0) = {e0, v2} 3890 $ cone(e0) = {v0, v1} 3891 If DMPlexStratify() is run on this mesh, it will give depths 3892 $ depth 0 = {v0, v1, v2} 3893 $ depth 1 = {e0, c0} 3894 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3895 3896 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3897 3898 Level: beginner 3899 3900 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3901 @*/ 3902 PetscErrorCode DMPlexStratify(DM dm) 3903 { 3904 DM_Plex *mesh = (DM_Plex*) dm->data; 3905 DMLabel label; 3906 PetscInt pStart, pEnd, p; 3907 PetscInt numRoots = 0, numLeaves = 0; 3908 PetscErrorCode ierr; 3909 3910 PetscFunctionBegin; 3911 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3912 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3913 3914 /* Create depth label */ 3915 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3916 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3917 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3918 3919 { 3920 /* Initialize roots and count leaves */ 3921 PetscInt sMin = PETSC_MAX_INT; 3922 PetscInt sMax = PETSC_MIN_INT; 3923 PetscInt coneSize, supportSize; 3924 3925 for (p = pStart; p < pEnd; ++p) { 3926 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3927 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3928 if (!coneSize && supportSize) { 3929 sMin = PetscMin(p, sMin); 3930 sMax = PetscMax(p, sMax); 3931 ++numRoots; 3932 } else if (!supportSize && coneSize) { 3933 ++numLeaves; 3934 } else if (!supportSize && !coneSize) { 3935 /* Isolated points */ 3936 sMin = PetscMin(p, sMin); 3937 sMax = PetscMax(p, sMax); 3938 } 3939 } 3940 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3941 } 3942 3943 if (numRoots + numLeaves == (pEnd - pStart)) { 3944 PetscInt sMin = PETSC_MAX_INT; 3945 PetscInt sMax = PETSC_MIN_INT; 3946 PetscInt coneSize, supportSize; 3947 3948 for (p = pStart; p < pEnd; ++p) { 3949 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3950 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3951 if (!supportSize && coneSize) { 3952 sMin = PetscMin(p, sMin); 3953 sMax = PetscMax(p, sMax); 3954 } 3955 } 3956 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3957 } else { 3958 PetscInt level = 0; 3959 PetscInt qStart, qEnd, q; 3960 3961 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3962 while (qEnd > qStart) { 3963 PetscInt sMin = PETSC_MAX_INT; 3964 PetscInt sMax = PETSC_MIN_INT; 3965 3966 for (q = qStart; q < qEnd; ++q) { 3967 const PetscInt *support; 3968 PetscInt supportSize, s; 3969 3970 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3971 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3972 for (s = 0; s < supportSize; ++s) { 3973 sMin = PetscMin(support[s], sMin); 3974 sMax = PetscMax(support[s], sMax); 3975 } 3976 } 3977 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3978 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3979 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3980 } 3981 } 3982 { /* just in case there is an empty process */ 3983 PetscInt numValues, maxValues = 0, v; 3984 3985 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3986 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3987 for (v = numValues; v < maxValues; v++) { 3988 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3989 } 3990 } 3991 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3992 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3993 PetscFunctionReturn(0); 3994 } 3995 3996 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3997 { 3998 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3999 PetscInt dim, depth, pheight, coneSize; 4000 PetscErrorCode ierr; 4001 4002 PetscFunctionBeginHot; 4003 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4004 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4005 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 4006 pheight = depth - pdepth; 4007 if (depth <= 1) { 4008 switch (pdepth) { 4009 case 0: ct = DM_POLYTOPE_POINT;break; 4010 case 1: 4011 switch (coneSize) { 4012 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4013 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4014 case 4: 4015 switch (dim) { 4016 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 4017 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 4018 default: break; 4019 } 4020 break; 4021 case 5: ct = DM_POLYTOPE_PYRAMID;break; 4022 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4023 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 4024 default: break; 4025 } 4026 } 4027 } else { 4028 if (pdepth == 0) { 4029 ct = DM_POLYTOPE_POINT; 4030 } else if (pheight == 0) { 4031 switch (dim) { 4032 case 1: 4033 switch (coneSize) { 4034 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4035 default: break; 4036 } 4037 break; 4038 case 2: 4039 switch (coneSize) { 4040 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4041 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4042 default: break; 4043 } 4044 break; 4045 case 3: 4046 switch (coneSize) { 4047 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 4048 case 5: 4049 { 4050 const PetscInt *cone; 4051 PetscInt faceConeSize; 4052 4053 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 4054 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 4055 switch (faceConeSize) { 4056 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4057 case 4: ct = DM_POLYTOPE_PYRAMID;break; 4058 } 4059 } 4060 break; 4061 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4062 default: break; 4063 } 4064 break; 4065 default: break; 4066 } 4067 } else if (pheight > 0) { 4068 switch (coneSize) { 4069 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4070 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4071 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4072 default: break; 4073 } 4074 } 4075 } 4076 *pt = ct; 4077 PetscFunctionReturn(0); 4078 } 4079 4080 /*@ 4081 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4082 4083 Collective on dm 4084 4085 Input Parameter: 4086 . mesh - The DMPlex 4087 4088 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4089 4090 Level: developer 4091 4092 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4093 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4094 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4095 4096 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 4097 @*/ 4098 PetscErrorCode DMPlexComputeCellTypes(DM dm) 4099 { 4100 DM_Plex *mesh; 4101 DMLabel ctLabel; 4102 PetscInt pStart, pEnd, p; 4103 PetscErrorCode ierr; 4104 4105 PetscFunctionBegin; 4106 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4107 mesh = (DM_Plex *) dm->data; 4108 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 4109 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 4110 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4111 for (p = pStart; p < pEnd; ++p) { 4112 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4113 PetscInt pdepth; 4114 4115 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 4116 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 4117 PetscCheckFalse(ct == DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 4118 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 4119 } 4120 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 4121 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 4122 PetscFunctionReturn(0); 4123 } 4124 4125 /*@C 4126 DMPlexGetJoin - Get an array for the join of the set of points 4127 4128 Not Collective 4129 4130 Input Parameters: 4131 + dm - The DMPlex object 4132 . numPoints - The number of input points for the join 4133 - points - The input points 4134 4135 Output Parameters: 4136 + numCoveredPoints - The number of points in the join 4137 - coveredPoints - The points in the join 4138 4139 Level: intermediate 4140 4141 Note: Currently, this is restricted to a single level join 4142 4143 Fortran Notes: 4144 Since it returns an array, this routine is only available in Fortran 90, and you must 4145 include petsc.h90 in your code. 4146 4147 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4148 4149 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 4150 @*/ 4151 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4152 { 4153 DM_Plex *mesh = (DM_Plex*) dm->data; 4154 PetscInt *join[2]; 4155 PetscInt joinSize, i = 0; 4156 PetscInt dof, off, p, c, m; 4157 PetscErrorCode ierr; 4158 4159 PetscFunctionBegin; 4160 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4161 PetscValidIntPointer(points, 3); 4162 PetscValidIntPointer(numCoveredPoints, 4); 4163 PetscValidPointer(coveredPoints, 5); 4164 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4165 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4166 /* Copy in support of first point */ 4167 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 4168 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 4169 for (joinSize = 0; joinSize < dof; ++joinSize) { 4170 join[i][joinSize] = mesh->supports[off+joinSize]; 4171 } 4172 /* Check each successive support */ 4173 for (p = 1; p < numPoints; ++p) { 4174 PetscInt newJoinSize = 0; 4175 4176 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 4177 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 4178 for (c = 0; c < dof; ++c) { 4179 const PetscInt point = mesh->supports[off+c]; 4180 4181 for (m = 0; m < joinSize; ++m) { 4182 if (point == join[i][m]) { 4183 join[1-i][newJoinSize++] = point; 4184 break; 4185 } 4186 } 4187 } 4188 joinSize = newJoinSize; 4189 i = 1-i; 4190 } 4191 *numCoveredPoints = joinSize; 4192 *coveredPoints = join[i]; 4193 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4194 PetscFunctionReturn(0); 4195 } 4196 4197 /*@C 4198 DMPlexRestoreJoin - Restore an array for the join of the set of points 4199 4200 Not Collective 4201 4202 Input Parameters: 4203 + dm - The DMPlex object 4204 . numPoints - The number of input points for the join 4205 - points - The input points 4206 4207 Output Parameters: 4208 + numCoveredPoints - The number of points in the join 4209 - coveredPoints - The points in the join 4210 4211 Fortran Notes: 4212 Since it returns an array, this routine is only available in Fortran 90, and you must 4213 include petsc.h90 in your code. 4214 4215 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4216 4217 Level: intermediate 4218 4219 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 4220 @*/ 4221 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4222 { 4223 PetscErrorCode ierr; 4224 4225 PetscFunctionBegin; 4226 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4227 if (points) PetscValidIntPointer(points,3); 4228 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4229 PetscValidPointer(coveredPoints, 5); 4230 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4231 if (numCoveredPoints) *numCoveredPoints = 0; 4232 PetscFunctionReturn(0); 4233 } 4234 4235 /*@C 4236 DMPlexGetFullJoin - Get an array for the join of the set of points 4237 4238 Not Collective 4239 4240 Input Parameters: 4241 + dm - The DMPlex object 4242 . numPoints - The number of input points for the join 4243 - points - The input points 4244 4245 Output Parameters: 4246 + numCoveredPoints - The number of points in the join 4247 - coveredPoints - The points in the join 4248 4249 Fortran Notes: 4250 Since it returns an array, this routine is only available in Fortran 90, and you must 4251 include petsc.h90 in your code. 4252 4253 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4254 4255 Level: intermediate 4256 4257 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 4258 @*/ 4259 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4260 { 4261 DM_Plex *mesh = (DM_Plex*) dm->data; 4262 PetscInt *offsets, **closures; 4263 PetscInt *join[2]; 4264 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 4265 PetscInt p, d, c, m, ms; 4266 PetscErrorCode ierr; 4267 4268 PetscFunctionBegin; 4269 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4270 PetscValidIntPointer(points, 3); 4271 PetscValidIntPointer(numCoveredPoints, 4); 4272 PetscValidPointer(coveredPoints, 5); 4273 4274 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4275 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 4276 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4277 ms = mesh->maxSupportSize; 4278 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 4279 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4280 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4281 4282 for (p = 0; p < numPoints; ++p) { 4283 PetscInt closureSize; 4284 4285 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 4286 4287 offsets[p*(depth+2)+0] = 0; 4288 for (d = 0; d < depth+1; ++d) { 4289 PetscInt pStart, pEnd, i; 4290 4291 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4292 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4293 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4294 offsets[p*(depth+2)+d+1] = i; 4295 break; 4296 } 4297 } 4298 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4299 } 4300 PetscCheckFalse(offsets[p*(depth+2)+depth+1] != closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 4301 } 4302 for (d = 0; d < depth+1; ++d) { 4303 PetscInt dof; 4304 4305 /* Copy in support of first point */ 4306 dof = offsets[d+1] - offsets[d]; 4307 for (joinSize = 0; joinSize < dof; ++joinSize) { 4308 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4309 } 4310 /* Check each successive cone */ 4311 for (p = 1; p < numPoints && joinSize; ++p) { 4312 PetscInt newJoinSize = 0; 4313 4314 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4315 for (c = 0; c < dof; ++c) { 4316 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4317 4318 for (m = 0; m < joinSize; ++m) { 4319 if (point == join[i][m]) { 4320 join[1-i][newJoinSize++] = point; 4321 break; 4322 } 4323 } 4324 } 4325 joinSize = newJoinSize; 4326 i = 1-i; 4327 } 4328 if (joinSize) break; 4329 } 4330 *numCoveredPoints = joinSize; 4331 *coveredPoints = join[i]; 4332 for (p = 0; p < numPoints; ++p) { 4333 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4334 } 4335 ierr = PetscFree(closures);CHKERRQ(ierr); 4336 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4337 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4338 PetscFunctionReturn(0); 4339 } 4340 4341 /*@C 4342 DMPlexGetMeet - Get an array for the meet of the set of points 4343 4344 Not Collective 4345 4346 Input Parameters: 4347 + dm - The DMPlex object 4348 . numPoints - The number of input points for the meet 4349 - points - The input points 4350 4351 Output Parameters: 4352 + numCoveredPoints - The number of points in the meet 4353 - coveredPoints - The points in the meet 4354 4355 Level: intermediate 4356 4357 Note: Currently, this is restricted to a single level meet 4358 4359 Fortran Notes: 4360 Since it returns an array, this routine is only available in Fortran 90, and you must 4361 include petsc.h90 in your code. 4362 4363 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4364 4365 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4366 @*/ 4367 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4368 { 4369 DM_Plex *mesh = (DM_Plex*) dm->data; 4370 PetscInt *meet[2]; 4371 PetscInt meetSize, i = 0; 4372 PetscInt dof, off, p, c, m; 4373 PetscErrorCode ierr; 4374 4375 PetscFunctionBegin; 4376 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4377 PetscValidPointer(points, 3); 4378 PetscValidPointer(numCoveringPoints, 4); 4379 PetscValidPointer(coveringPoints, 5); 4380 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4381 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4382 /* Copy in cone of first point */ 4383 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4384 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4385 for (meetSize = 0; meetSize < dof; ++meetSize) { 4386 meet[i][meetSize] = mesh->cones[off+meetSize]; 4387 } 4388 /* Check each successive cone */ 4389 for (p = 1; p < numPoints; ++p) { 4390 PetscInt newMeetSize = 0; 4391 4392 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4393 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4394 for (c = 0; c < dof; ++c) { 4395 const PetscInt point = mesh->cones[off+c]; 4396 4397 for (m = 0; m < meetSize; ++m) { 4398 if (point == meet[i][m]) { 4399 meet[1-i][newMeetSize++] = point; 4400 break; 4401 } 4402 } 4403 } 4404 meetSize = newMeetSize; 4405 i = 1-i; 4406 } 4407 *numCoveringPoints = meetSize; 4408 *coveringPoints = meet[i]; 4409 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4410 PetscFunctionReturn(0); 4411 } 4412 4413 /*@C 4414 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4415 4416 Not Collective 4417 4418 Input Parameters: 4419 + dm - The DMPlex object 4420 . numPoints - The number of input points for the meet 4421 - points - The input points 4422 4423 Output Parameters: 4424 + numCoveredPoints - The number of points in the meet 4425 - coveredPoints - The points in the meet 4426 4427 Level: intermediate 4428 4429 Fortran Notes: 4430 Since it returns an array, this routine is only available in Fortran 90, and you must 4431 include petsc.h90 in your code. 4432 4433 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4434 4435 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4436 @*/ 4437 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4438 { 4439 PetscErrorCode ierr; 4440 4441 PetscFunctionBegin; 4442 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4443 if (points) PetscValidIntPointer(points,3); 4444 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4445 PetscValidPointer(coveredPoints,5); 4446 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4447 if (numCoveredPoints) *numCoveredPoints = 0; 4448 PetscFunctionReturn(0); 4449 } 4450 4451 /*@C 4452 DMPlexGetFullMeet - Get an array for the meet of the set of points 4453 4454 Not Collective 4455 4456 Input Parameters: 4457 + dm - The DMPlex object 4458 . numPoints - The number of input points for the meet 4459 - points - The input points 4460 4461 Output Parameters: 4462 + numCoveredPoints - The number of points in the meet 4463 - coveredPoints - The points in the meet 4464 4465 Level: intermediate 4466 4467 Fortran Notes: 4468 Since it returns an array, this routine is only available in Fortran 90, and you must 4469 include petsc.h90 in your code. 4470 4471 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4472 4473 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4474 @*/ 4475 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4476 { 4477 DM_Plex *mesh = (DM_Plex*) dm->data; 4478 PetscInt *offsets, **closures; 4479 PetscInt *meet[2]; 4480 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4481 PetscInt p, h, c, m, mc; 4482 PetscErrorCode ierr; 4483 4484 PetscFunctionBegin; 4485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4486 PetscValidPointer(points, 3); 4487 PetscValidPointer(numCoveredPoints, 4); 4488 PetscValidPointer(coveredPoints, 5); 4489 4490 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4491 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4492 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4493 mc = mesh->maxConeSize; 4494 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4495 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4496 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4497 4498 for (p = 0; p < numPoints; ++p) { 4499 PetscInt closureSize; 4500 4501 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4502 4503 offsets[p*(height+2)+0] = 0; 4504 for (h = 0; h < height+1; ++h) { 4505 PetscInt pStart, pEnd, i; 4506 4507 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4508 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4509 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4510 offsets[p*(height+2)+h+1] = i; 4511 break; 4512 } 4513 } 4514 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4515 } 4516 PetscCheckFalse(offsets[p*(height+2)+height+1] != closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 4517 } 4518 for (h = 0; h < height+1; ++h) { 4519 PetscInt dof; 4520 4521 /* Copy in cone of first point */ 4522 dof = offsets[h+1] - offsets[h]; 4523 for (meetSize = 0; meetSize < dof; ++meetSize) { 4524 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4525 } 4526 /* Check each successive cone */ 4527 for (p = 1; p < numPoints && meetSize; ++p) { 4528 PetscInt newMeetSize = 0; 4529 4530 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4531 for (c = 0; c < dof; ++c) { 4532 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4533 4534 for (m = 0; m < meetSize; ++m) { 4535 if (point == meet[i][m]) { 4536 meet[1-i][newMeetSize++] = point; 4537 break; 4538 } 4539 } 4540 } 4541 meetSize = newMeetSize; 4542 i = 1-i; 4543 } 4544 if (meetSize) break; 4545 } 4546 *numCoveredPoints = meetSize; 4547 *coveredPoints = meet[i]; 4548 for (p = 0; p < numPoints; ++p) { 4549 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4550 } 4551 ierr = PetscFree(closures);CHKERRQ(ierr); 4552 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4553 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4554 PetscFunctionReturn(0); 4555 } 4556 4557 /*@C 4558 DMPlexEqual - Determine if two DMs have the same topology 4559 4560 Not Collective 4561 4562 Input Parameters: 4563 + dmA - A DMPlex object 4564 - dmB - A DMPlex object 4565 4566 Output Parameters: 4567 . equal - PETSC_TRUE if the topologies are identical 4568 4569 Level: intermediate 4570 4571 Notes: 4572 We are not solving graph isomorphism, so we do not permutation. 4573 4574 .seealso: DMPlexGetCone() 4575 @*/ 4576 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4577 { 4578 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4579 PetscErrorCode ierr; 4580 4581 PetscFunctionBegin; 4582 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4583 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4584 PetscValidPointer(equal, 3); 4585 4586 *equal = PETSC_FALSE; 4587 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4588 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4589 if (depth != depthB) PetscFunctionReturn(0); 4590 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4591 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4592 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4593 for (p = pStart; p < pEnd; ++p) { 4594 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4595 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4596 4597 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4598 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4599 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4600 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4601 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4602 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4603 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4604 for (c = 0; c < coneSize; ++c) { 4605 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4606 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4607 } 4608 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4609 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4610 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4611 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4612 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4613 for (s = 0; s < supportSize; ++s) { 4614 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4615 } 4616 } 4617 *equal = PETSC_TRUE; 4618 PetscFunctionReturn(0); 4619 } 4620 4621 /*@C 4622 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4623 4624 Not Collective 4625 4626 Input Parameters: 4627 + dm - The DMPlex 4628 . cellDim - The cell dimension 4629 - numCorners - The number of vertices on a cell 4630 4631 Output Parameters: 4632 . numFaceVertices - The number of vertices on a face 4633 4634 Level: developer 4635 4636 Notes: 4637 Of course this can only work for a restricted set of symmetric shapes 4638 4639 .seealso: DMPlexGetCone() 4640 @*/ 4641 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4642 { 4643 MPI_Comm comm; 4644 PetscErrorCode ierr; 4645 4646 PetscFunctionBegin; 4647 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4648 PetscValidPointer(numFaceVertices,4); 4649 switch (cellDim) { 4650 case 0: 4651 *numFaceVertices = 0; 4652 break; 4653 case 1: 4654 *numFaceVertices = 1; 4655 break; 4656 case 2: 4657 switch (numCorners) { 4658 case 3: /* triangle */ 4659 *numFaceVertices = 2; /* Edge has 2 vertices */ 4660 break; 4661 case 4: /* quadrilateral */ 4662 *numFaceVertices = 2; /* Edge has 2 vertices */ 4663 break; 4664 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4665 *numFaceVertices = 3; /* Edge has 3 vertices */ 4666 break; 4667 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4668 *numFaceVertices = 3; /* Edge has 3 vertices */ 4669 break; 4670 default: 4671 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4672 } 4673 break; 4674 case 3: 4675 switch (numCorners) { 4676 case 4: /* tetradehdron */ 4677 *numFaceVertices = 3; /* Face has 3 vertices */ 4678 break; 4679 case 6: /* tet cohesive cells */ 4680 *numFaceVertices = 4; /* Face has 4 vertices */ 4681 break; 4682 case 8: /* hexahedron */ 4683 *numFaceVertices = 4; /* Face has 4 vertices */ 4684 break; 4685 case 9: /* tet cohesive Lagrange cells */ 4686 *numFaceVertices = 6; /* Face has 6 vertices */ 4687 break; 4688 case 10: /* quadratic tetrahedron */ 4689 *numFaceVertices = 6; /* Face has 6 vertices */ 4690 break; 4691 case 12: /* hex cohesive Lagrange cells */ 4692 *numFaceVertices = 6; /* Face has 6 vertices */ 4693 break; 4694 case 18: /* quadratic tet cohesive Lagrange cells */ 4695 *numFaceVertices = 6; /* Face has 6 vertices */ 4696 break; 4697 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4698 *numFaceVertices = 9; /* Face has 9 vertices */ 4699 break; 4700 default: 4701 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4702 } 4703 break; 4704 default: 4705 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4706 } 4707 PetscFunctionReturn(0); 4708 } 4709 4710 /*@ 4711 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4712 4713 Not Collective 4714 4715 Input Parameter: 4716 . dm - The DMPlex object 4717 4718 Output Parameter: 4719 . depthLabel - The DMLabel recording point depth 4720 4721 Level: developer 4722 4723 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4724 @*/ 4725 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4726 { 4727 PetscFunctionBegin; 4728 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4729 PetscValidPointer(depthLabel, 2); 4730 *depthLabel = dm->depthLabel; 4731 PetscFunctionReturn(0); 4732 } 4733 4734 /*@ 4735 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4736 4737 Not Collective 4738 4739 Input Parameter: 4740 . dm - The DMPlex object 4741 4742 Output Parameter: 4743 . depth - The number of strata (breadth first levels) in the DAG 4744 4745 Level: developer 4746 4747 Notes: 4748 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4749 The point depth is described more in detail in DMPlexGetDepthStratum(). 4750 An empty mesh gives -1. 4751 4752 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4753 @*/ 4754 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4755 { 4756 DMLabel label; 4757 PetscInt d = 0; 4758 PetscErrorCode ierr; 4759 4760 PetscFunctionBegin; 4761 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4762 PetscValidPointer(depth, 2); 4763 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4764 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4765 *depth = d-1; 4766 PetscFunctionReturn(0); 4767 } 4768 4769 /*@ 4770 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4771 4772 Not Collective 4773 4774 Input Parameters: 4775 + dm - The DMPlex object 4776 - stratumValue - The requested depth 4777 4778 Output Parameters: 4779 + start - The first point at this depth 4780 - end - One beyond the last point at this depth 4781 4782 Notes: 4783 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4784 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4785 higher dimension, e.g., "edges". 4786 4787 Level: developer 4788 4789 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4790 @*/ 4791 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4792 { 4793 DMLabel label; 4794 PetscInt pStart, pEnd; 4795 PetscErrorCode ierr; 4796 4797 PetscFunctionBegin; 4798 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4799 if (start) {PetscValidPointer(start, 3); *start = 0;} 4800 if (end) {PetscValidPointer(end, 4); *end = 0;} 4801 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4802 if (pStart == pEnd) PetscFunctionReturn(0); 4803 if (stratumValue < 0) { 4804 if (start) *start = pStart; 4805 if (end) *end = pEnd; 4806 PetscFunctionReturn(0); 4807 } 4808 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4809 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4810 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4811 PetscFunctionReturn(0); 4812 } 4813 4814 /*@ 4815 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4816 4817 Not Collective 4818 4819 Input Parameters: 4820 + dm - The DMPlex object 4821 - stratumValue - The requested height 4822 4823 Output Parameters: 4824 + start - The first point at this height 4825 - end - One beyond the last point at this height 4826 4827 Notes: 4828 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4829 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4830 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4831 4832 Level: developer 4833 4834 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4835 @*/ 4836 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4837 { 4838 DMLabel label; 4839 PetscInt depth, pStart, pEnd; 4840 PetscErrorCode ierr; 4841 4842 PetscFunctionBegin; 4843 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4844 if (start) {PetscValidPointer(start, 3); *start = 0;} 4845 if (end) {PetscValidPointer(end, 4); *end = 0;} 4846 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4847 if (pStart == pEnd) PetscFunctionReturn(0); 4848 if (stratumValue < 0) { 4849 if (start) *start = pStart; 4850 if (end) *end = pEnd; 4851 PetscFunctionReturn(0); 4852 } 4853 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4854 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4855 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4856 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4857 PetscFunctionReturn(0); 4858 } 4859 4860 /*@ 4861 DMPlexGetPointDepth - Get the depth of a given point 4862 4863 Not Collective 4864 4865 Input Parameters: 4866 + dm - The DMPlex object 4867 - point - The point 4868 4869 Output Parameter: 4870 . depth - The depth of the point 4871 4872 Level: intermediate 4873 4874 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4875 @*/ 4876 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4877 { 4878 PetscErrorCode ierr; 4879 4880 PetscFunctionBegin; 4881 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4882 PetscValidIntPointer(depth, 3); 4883 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4884 PetscFunctionReturn(0); 4885 } 4886 4887 /*@ 4888 DMPlexGetPointHeight - Get the height of a given point 4889 4890 Not Collective 4891 4892 Input Parameters: 4893 + dm - The DMPlex object 4894 - point - The point 4895 4896 Output Parameter: 4897 . height - The height of the point 4898 4899 Level: intermediate 4900 4901 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4902 @*/ 4903 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4904 { 4905 PetscInt n, pDepth; 4906 PetscErrorCode ierr; 4907 4908 PetscFunctionBegin; 4909 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4910 PetscValidIntPointer(height, 3); 4911 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4912 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4913 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4914 PetscFunctionReturn(0); 4915 } 4916 4917 /*@ 4918 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4919 4920 Not Collective 4921 4922 Input Parameter: 4923 . dm - The DMPlex object 4924 4925 Output Parameter: 4926 . celltypeLabel - The DMLabel recording cell polytope type 4927 4928 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4929 DMCreateLabel(dm, "celltype") beforehand. 4930 4931 Level: developer 4932 4933 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4934 @*/ 4935 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4936 { 4937 PetscErrorCode ierr; 4938 4939 PetscFunctionBegin; 4940 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4941 PetscValidPointer(celltypeLabel, 2); 4942 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4943 *celltypeLabel = dm->celltypeLabel; 4944 PetscFunctionReturn(0); 4945 } 4946 4947 /*@ 4948 DMPlexGetCellType - Get the polytope type of a given cell 4949 4950 Not Collective 4951 4952 Input Parameters: 4953 + dm - The DMPlex object 4954 - cell - The cell 4955 4956 Output Parameter: 4957 . celltype - The polytope type of the cell 4958 4959 Level: intermediate 4960 4961 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4962 @*/ 4963 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4964 { 4965 DMLabel label; 4966 PetscInt ct; 4967 PetscErrorCode ierr; 4968 4969 PetscFunctionBegin; 4970 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4971 PetscValidPointer(celltype, 3); 4972 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4973 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4974 PetscCheckFalse(ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4975 *celltype = (DMPolytopeType) ct; 4976 PetscFunctionReturn(0); 4977 } 4978 4979 /*@ 4980 DMPlexSetCellType - Set the polytope type of a given cell 4981 4982 Not Collective 4983 4984 Input Parameters: 4985 + dm - The DMPlex object 4986 . cell - The cell 4987 - celltype - The polytope type of the cell 4988 4989 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4990 is executed. This function will override the computed type. However, if automatic classification will not succeed 4991 and a user wants to manually specify all types, the classification must be disabled by calling 4992 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4993 4994 Level: advanced 4995 4996 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4997 @*/ 4998 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4999 { 5000 DMLabel label; 5001 PetscErrorCode ierr; 5002 5003 PetscFunctionBegin; 5004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5005 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 5006 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 5007 PetscFunctionReturn(0); 5008 } 5009 5010 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5011 { 5012 PetscSection section, s; 5013 Mat m; 5014 PetscInt maxHeight; 5015 PetscErrorCode ierr; 5016 5017 PetscFunctionBegin; 5018 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 5019 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 5020 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 5021 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5022 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 5023 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5024 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 5025 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 5026 ierr = DMSetDefaultConstraints(*cdm, s, m, NULL);CHKERRQ(ierr); 5027 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 5028 ierr = MatDestroy(&m);CHKERRQ(ierr); 5029 5030 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 5031 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 5032 PetscFunctionReturn(0); 5033 } 5034 5035 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5036 { 5037 Vec coordsLocal; 5038 DM coordsDM; 5039 PetscErrorCode ierr; 5040 5041 PetscFunctionBegin; 5042 *field = NULL; 5043 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 5044 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 5045 if (coordsLocal && coordsDM) { 5046 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 5047 } 5048 PetscFunctionReturn(0); 5049 } 5050 5051 /*@C 5052 DMPlexGetConeSection - Return a section which describes the layout of cone data 5053 5054 Not Collective 5055 5056 Input Parameters: 5057 . dm - The DMPlex object 5058 5059 Output Parameter: 5060 . section - The PetscSection object 5061 5062 Level: developer 5063 5064 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 5065 @*/ 5066 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5067 { 5068 DM_Plex *mesh = (DM_Plex*) dm->data; 5069 5070 PetscFunctionBegin; 5071 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5072 if (section) *section = mesh->coneSection; 5073 PetscFunctionReturn(0); 5074 } 5075 5076 /*@C 5077 DMPlexGetSupportSection - Return a section which describes the layout of support data 5078 5079 Not Collective 5080 5081 Input Parameters: 5082 . dm - The DMPlex object 5083 5084 Output Parameter: 5085 . section - The PetscSection object 5086 5087 Level: developer 5088 5089 .seealso: DMPlexGetConeSection() 5090 @*/ 5091 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5092 { 5093 DM_Plex *mesh = (DM_Plex*) dm->data; 5094 5095 PetscFunctionBegin; 5096 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5097 if (section) *section = mesh->supportSection; 5098 PetscFunctionReturn(0); 5099 } 5100 5101 /*@C 5102 DMPlexGetCones - Return cone data 5103 5104 Not Collective 5105 5106 Input Parameters: 5107 . dm - The DMPlex object 5108 5109 Output Parameter: 5110 . cones - The cone for each point 5111 5112 Level: developer 5113 5114 .seealso: DMPlexGetConeSection() 5115 @*/ 5116 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5117 { 5118 DM_Plex *mesh = (DM_Plex*) dm->data; 5119 5120 PetscFunctionBegin; 5121 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5122 if (cones) *cones = mesh->cones; 5123 PetscFunctionReturn(0); 5124 } 5125 5126 /*@C 5127 DMPlexGetConeOrientations - Return cone orientation data 5128 5129 Not Collective 5130 5131 Input Parameters: 5132 . dm - The DMPlex object 5133 5134 Output Parameter: 5135 . coneOrientations - The array of cone orientations for all points 5136 5137 Level: developer 5138 5139 Notes: 5140 The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5141 5142 The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5143 5144 .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation() 5145 @*/ 5146 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5147 { 5148 DM_Plex *mesh = (DM_Plex*) dm->data; 5149 5150 PetscFunctionBegin; 5151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5152 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5153 PetscFunctionReturn(0); 5154 } 5155 5156 /******************************** FEM Support **********************************/ 5157 5158 /* 5159 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 5160 representing a line in the section. 5161 */ 5162 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 5163 { 5164 PetscErrorCode ierr; 5165 5166 PetscFunctionBeginHot; 5167 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 5168 if (line < 0) { 5169 *k = 0; 5170 *Nc = 0; 5171 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 5172 *k = 1; 5173 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 5174 /* An order k SEM disc has k-1 dofs on an edge */ 5175 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 5176 *k = *k / *Nc + 1; 5177 } 5178 PetscFunctionReturn(0); 5179 } 5180 5181 /*@ 5182 5183 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5184 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 5185 section provided (or the section of the DM). 5186 5187 Input Parameters: 5188 + dm - The DM 5189 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5190 - section - The PetscSection to reorder, or NULL for the default section 5191 5192 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5193 degree of the basis. 5194 5195 Example: 5196 A typical interpolated single-quad mesh might order points as 5197 .vb 5198 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5199 5200 v4 -- e6 -- v3 5201 | | 5202 e7 c0 e8 5203 | | 5204 v1 -- e5 -- v2 5205 .ve 5206 5207 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5208 dofs in the order of points, e.g., 5209 .vb 5210 c0 -> [0,1,2,3] 5211 v1 -> [4] 5212 ... 5213 e5 -> [8, 9] 5214 .ve 5215 5216 which corresponds to the dofs 5217 .vb 5218 6 10 11 7 5219 13 2 3 15 5220 12 0 1 14 5221 4 8 9 5 5222 .ve 5223 5224 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5225 .vb 5226 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5227 .ve 5228 5229 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5230 .vb 5231 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5232 .ve 5233 5234 Level: developer 5235 5236 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 5237 @*/ 5238 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5239 { 5240 DMLabel label; 5241 PetscInt dim, depth = -1, eStart = -1, Nf; 5242 PetscBool vertexchart; 5243 PetscErrorCode ierr; 5244 5245 PetscFunctionBegin; 5246 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5247 if (dim < 1) PetscFunctionReturn(0); 5248 if (point < 0) { 5249 PetscInt sStart,sEnd; 5250 5251 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 5252 point = sEnd-sStart ? sStart : point; 5253 } 5254 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 5255 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 5256 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5257 if (depth == 1) {eStart = point;} 5258 else if (depth == dim) { 5259 const PetscInt *cone; 5260 5261 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5262 if (dim == 2) eStart = cone[0]; 5263 else if (dim == 3) { 5264 const PetscInt *cone2; 5265 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 5266 eStart = cone2[0]; 5267 } else SETERRQ(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); 5268 } else PetscCheckFalse(depth >= 0,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); 5269 { /* Determine whether the chart covers all points or just vertices. */ 5270 PetscInt pStart,pEnd,cStart,cEnd; 5271 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 5272 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 5273 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5274 else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5275 else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 5276 } 5277 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5278 for (PetscInt d=1; d<=dim; d++) { 5279 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5280 PetscInt *perm; 5281 5282 for (f = 0; f < Nf; ++f) { 5283 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5284 size += PetscPowInt(k+1, d)*Nc; 5285 } 5286 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 5287 for (f = 0; f < Nf; ++f) { 5288 switch (d) { 5289 case 1: 5290 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5291 /* 5292 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5293 We want [ vtx0; edge of length k-1; vtx1 ] 5294 */ 5295 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5296 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5297 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5298 foffset = offset; 5299 break; 5300 case 2: 5301 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5302 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5303 /* The SEM order is 5304 5305 v_lb, {e_b}, v_rb, 5306 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5307 v_lt, reverse {e_t}, v_rt 5308 */ 5309 { 5310 const PetscInt of = 0; 5311 const PetscInt oeb = of + PetscSqr(k-1); 5312 const PetscInt oer = oeb + (k-1); 5313 const PetscInt oet = oer + (k-1); 5314 const PetscInt oel = oet + (k-1); 5315 const PetscInt ovlb = oel + (k-1); 5316 const PetscInt ovrb = ovlb + 1; 5317 const PetscInt ovrt = ovrb + 1; 5318 const PetscInt ovlt = ovrt + 1; 5319 PetscInt o; 5320 5321 /* bottom */ 5322 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5323 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5324 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5325 /* middle */ 5326 for (i = 0; i < k-1; ++i) { 5327 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5328 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; 5329 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5330 } 5331 /* top */ 5332 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5333 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5334 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5335 foffset = offset; 5336 } 5337 break; 5338 case 3: 5339 /* The original hex closure is 5340 5341 {c, 5342 f_b, f_t, f_f, f_b, f_r, f_l, 5343 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5344 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5345 */ 5346 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5347 /* The SEM order is 5348 Bottom Slice 5349 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5350 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5351 v_blb, {e_bb}, v_brb, 5352 5353 Middle Slice (j) 5354 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5355 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5356 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5357 5358 Top Slice 5359 v_tlf, {e_tf}, v_trf, 5360 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5361 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5362 */ 5363 { 5364 const PetscInt oc = 0; 5365 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5366 const PetscInt oft = ofb + PetscSqr(k-1); 5367 const PetscInt off = oft + PetscSqr(k-1); 5368 const PetscInt ofk = off + PetscSqr(k-1); 5369 const PetscInt ofr = ofk + PetscSqr(k-1); 5370 const PetscInt ofl = ofr + PetscSqr(k-1); 5371 const PetscInt oebl = ofl + PetscSqr(k-1); 5372 const PetscInt oebb = oebl + (k-1); 5373 const PetscInt oebr = oebb + (k-1); 5374 const PetscInt oebf = oebr + (k-1); 5375 const PetscInt oetf = oebf + (k-1); 5376 const PetscInt oetr = oetf + (k-1); 5377 const PetscInt oetb = oetr + (k-1); 5378 const PetscInt oetl = oetb + (k-1); 5379 const PetscInt oerf = oetl + (k-1); 5380 const PetscInt oelf = oerf + (k-1); 5381 const PetscInt oelb = oelf + (k-1); 5382 const PetscInt oerb = oelb + (k-1); 5383 const PetscInt ovblf = oerb + (k-1); 5384 const PetscInt ovblb = ovblf + 1; 5385 const PetscInt ovbrb = ovblb + 1; 5386 const PetscInt ovbrf = ovbrb + 1; 5387 const PetscInt ovtlf = ovbrf + 1; 5388 const PetscInt ovtrf = ovtlf + 1; 5389 const PetscInt ovtrb = ovtrf + 1; 5390 const PetscInt ovtlb = ovtrb + 1; 5391 PetscInt o, n; 5392 5393 /* Bottom Slice */ 5394 /* bottom */ 5395 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5396 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5397 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5398 /* middle */ 5399 for (i = 0; i < k-1; ++i) { 5400 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5401 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;} 5402 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5403 } 5404 /* top */ 5405 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5406 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5407 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5408 5409 /* Middle Slice */ 5410 for (j = 0; j < k-1; ++j) { 5411 /* bottom */ 5412 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5413 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; 5414 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5415 /* middle */ 5416 for (i = 0; i < k-1; ++i) { 5417 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5418 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; 5419 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5420 } 5421 /* top */ 5422 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5423 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; 5424 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5425 } 5426 5427 /* Top Slice */ 5428 /* bottom */ 5429 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5430 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5431 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5432 /* middle */ 5433 for (i = 0; i < k-1; ++i) { 5434 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5435 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5436 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5437 } 5438 /* top */ 5439 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5440 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5441 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5442 5443 foffset = offset; 5444 } 5445 break; 5446 default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5447 } 5448 } 5449 PetscCheckFalse(offset != size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5450 /* Check permutation */ 5451 { 5452 PetscInt *check; 5453 5454 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5455 for (i = 0; i < size; ++i) {check[i] = -1; PetscCheckFalse(perm[i] < 0 || perm[i] >= size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%D] = %D", i, perm[i]);} 5456 for (i = 0; i < size; ++i) check[perm[i]] = i; 5457 for (i = 0; i < size; ++i) {PetscCheckFalse(check[i] < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5458 ierr = PetscFree(check);CHKERRQ(ierr); 5459 } 5460 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5461 if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5462 PetscInt *loc_perm; 5463 ierr = PetscMalloc1(size*2, &loc_perm);CHKERRQ(ierr); 5464 for (PetscInt i=0; i<size; i++) { 5465 loc_perm[i] = perm[i]; 5466 loc_perm[size+i] = size + perm[i]; 5467 } 5468 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm);CHKERRQ(ierr); 5469 } 5470 } 5471 PetscFunctionReturn(0); 5472 } 5473 5474 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5475 { 5476 PetscDS prob; 5477 PetscInt depth, Nf, h; 5478 DMLabel label; 5479 PetscErrorCode ierr; 5480 5481 PetscFunctionBeginHot; 5482 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5483 Nf = prob->Nf; 5484 label = dm->depthLabel; 5485 *dspace = NULL; 5486 if (field < Nf) { 5487 PetscObject disc = prob->disc[field]; 5488 5489 if (disc->classid == PETSCFE_CLASSID) { 5490 PetscDualSpace dsp; 5491 5492 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5493 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5494 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5495 h = depth - 1 - h; 5496 if (h) { 5497 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5498 } else { 5499 *dspace = dsp; 5500 } 5501 } 5502 } 5503 PetscFunctionReturn(0); 5504 } 5505 5506 static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5507 { 5508 PetscScalar *array, *vArray; 5509 const PetscInt *cone, *coneO; 5510 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5511 PetscErrorCode ierr; 5512 5513 PetscFunctionBeginHot; 5514 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5515 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5516 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5517 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5518 if (!values || !*values) { 5519 if ((point >= pStart) && (point < pEnd)) { 5520 PetscInt dof; 5521 5522 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5523 size += dof; 5524 } 5525 for (p = 0; p < numPoints; ++p) { 5526 const PetscInt cp = cone[p]; 5527 PetscInt dof; 5528 5529 if ((cp < pStart) || (cp >= pEnd)) continue; 5530 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5531 size += dof; 5532 } 5533 if (!values) { 5534 if (csize) *csize = size; 5535 PetscFunctionReturn(0); 5536 } 5537 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5538 } else { 5539 array = *values; 5540 } 5541 size = 0; 5542 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5543 if ((point >= pStart) && (point < pEnd)) { 5544 PetscInt dof, off, d; 5545 PetscScalar *varr; 5546 5547 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5548 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5549 varr = &vArray[off]; 5550 for (d = 0; d < dof; ++d, ++offset) { 5551 array[offset] = varr[d]; 5552 } 5553 size += dof; 5554 } 5555 for (p = 0; p < numPoints; ++p) { 5556 const PetscInt cp = cone[p]; 5557 PetscInt o = coneO[p]; 5558 PetscInt dof, off, d; 5559 PetscScalar *varr; 5560 5561 if ((cp < pStart) || (cp >= pEnd)) continue; 5562 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5563 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5564 varr = &vArray[off]; 5565 if (o >= 0) { 5566 for (d = 0; d < dof; ++d, ++offset) { 5567 array[offset] = varr[d]; 5568 } 5569 } else { 5570 for (d = dof-1; d >= 0; --d, ++offset) { 5571 array[offset] = varr[d]; 5572 } 5573 } 5574 size += dof; 5575 } 5576 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5577 if (!*values) { 5578 if (csize) *csize = size; 5579 *values = array; 5580 } else { 5581 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5582 *csize = size; 5583 } 5584 PetscFunctionReturn(0); 5585 } 5586 5587 /* Compress out points not in the section */ 5588 static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5589 { 5590 const PetscInt np = *numPoints; 5591 PetscInt pStart, pEnd, p, q; 5592 PetscErrorCode ierr; 5593 5594 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5595 for (p = 0, q = 0; p < np; ++p) { 5596 const PetscInt r = points[p*2]; 5597 if ((r >= pStart) && (r < pEnd)) { 5598 points[q*2] = r; 5599 points[q*2+1] = points[p*2+1]; 5600 ++q; 5601 } 5602 } 5603 *numPoints = q; 5604 return 0; 5605 } 5606 5607 /* Compressed closure does not apply closure permutation */ 5608 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5609 { 5610 const PetscInt *cla = NULL; 5611 PetscInt np, *pts = NULL; 5612 PetscErrorCode ierr; 5613 5614 PetscFunctionBeginHot; 5615 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5616 if (*clPoints) { 5617 PetscInt dof, off; 5618 5619 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5620 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5621 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5622 np = dof/2; 5623 pts = (PetscInt *) &cla[off]; 5624 } else { 5625 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5626 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5627 } 5628 *numPoints = np; 5629 *points = pts; 5630 *clp = cla; 5631 PetscFunctionReturn(0); 5632 } 5633 5634 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5635 { 5636 PetscErrorCode ierr; 5637 5638 PetscFunctionBeginHot; 5639 if (!*clPoints) { 5640 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5641 } else { 5642 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5643 } 5644 *numPoints = 0; 5645 *points = NULL; 5646 *clSec = NULL; 5647 *clPoints = NULL; 5648 *clp = NULL; 5649 PetscFunctionReturn(0); 5650 } 5651 5652 static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 5653 { 5654 PetscInt offset = 0, p; 5655 const PetscInt **perms = NULL; 5656 const PetscScalar **flips = NULL; 5657 PetscErrorCode ierr; 5658 5659 PetscFunctionBeginHot; 5660 *size = 0; 5661 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5662 for (p = 0; p < numPoints; p++) { 5663 const PetscInt point = points[2*p]; 5664 const PetscInt *perm = perms ? perms[p] : NULL; 5665 const PetscScalar *flip = flips ? flips[p] : NULL; 5666 PetscInt dof, off, d; 5667 const PetscScalar *varr; 5668 5669 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5670 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5671 varr = &vArray[off]; 5672 if (clperm) { 5673 if (perm) { 5674 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5675 } else { 5676 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5677 } 5678 if (flip) { 5679 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5680 } 5681 } else { 5682 if (perm) { 5683 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5684 } else { 5685 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5686 } 5687 if (flip) { 5688 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5689 } 5690 } 5691 offset += dof; 5692 } 5693 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5694 *size = offset; 5695 PetscFunctionReturn(0); 5696 } 5697 5698 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[]) 5699 { 5700 PetscInt offset = 0, f; 5701 PetscErrorCode ierr; 5702 5703 PetscFunctionBeginHot; 5704 *size = 0; 5705 for (f = 0; f < numFields; ++f) { 5706 PetscInt p; 5707 const PetscInt **perms = NULL; 5708 const PetscScalar **flips = NULL; 5709 5710 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5711 for (p = 0; p < numPoints; p++) { 5712 const PetscInt point = points[2*p]; 5713 PetscInt fdof, foff, b; 5714 const PetscScalar *varr; 5715 const PetscInt *perm = perms ? perms[p] : NULL; 5716 const PetscScalar *flip = flips ? flips[p] : NULL; 5717 5718 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5719 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5720 varr = &vArray[foff]; 5721 if (clperm) { 5722 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5723 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5724 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5725 } else { 5726 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5727 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5728 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5729 } 5730 offset += fdof; 5731 } 5732 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5733 } 5734 *size = offset; 5735 PetscFunctionReturn(0); 5736 } 5737 5738 /*@C 5739 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5740 5741 Not collective 5742 5743 Input Parameters: 5744 + dm - The DM 5745 . section - The section describing the layout in v, or NULL to use the default section 5746 . v - The local vector 5747 - point - The point in the DM 5748 5749 Input/Output Parameters: 5750 + csize - The size of the input values array, or NULL; on output the number of values in the closure 5751 - values - An array to use for the values, or NULL to have it allocated automatically; 5752 if the user provided NULL, it is a borrowed array and should not be freed 5753 5754 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5755 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5756 $ assembly function, and a user may already have allocated storage for this operation. 5757 $ 5758 $ A typical use could be 5759 $ 5760 $ values = NULL; 5761 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5762 $ for (cl = 0; cl < clSize; ++cl) { 5763 $ <Compute on closure> 5764 $ } 5765 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5766 $ 5767 $ or 5768 $ 5769 $ PetscMalloc1(clMaxSize, &values); 5770 $ for (p = pStart; p < pEnd; ++p) { 5771 $ clSize = clMaxSize; 5772 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5773 $ for (cl = 0; cl < clSize; ++cl) { 5774 $ <Compute on closure> 5775 $ } 5776 $ } 5777 $ PetscFree(values); 5778 5779 Fortran Notes: 5780 Since it returns an array, this routine is only available in Fortran 90, and you must 5781 include petsc.h90 in your code. 5782 5783 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5784 5785 Level: intermediate 5786 5787 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5788 @*/ 5789 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5790 { 5791 PetscSection clSection; 5792 IS clPoints; 5793 PetscInt *points = NULL; 5794 const PetscInt *clp, *perm; 5795 PetscInt depth, numFields, numPoints, asize; 5796 PetscErrorCode ierr; 5797 5798 PetscFunctionBeginHot; 5799 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5800 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5801 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5802 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5803 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5804 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5805 if (depth == 1 && numFields < 2) { 5806 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5807 PetscFunctionReturn(0); 5808 } 5809 /* Get points */ 5810 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5811 /* Get sizes */ 5812 asize = 0; 5813 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5814 PetscInt dof; 5815 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5816 asize += dof; 5817 } 5818 if (values) { 5819 const PetscScalar *vArray; 5820 PetscInt size; 5821 5822 if (*values) { 5823 PetscCheckFalse(*csize < asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize); 5824 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5825 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5826 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5827 /* Get values */ 5828 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5829 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5830 PetscCheckFalse(asize != size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5831 /* Cleanup array */ 5832 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5833 } 5834 if (csize) *csize = asize; 5835 /* Cleanup points */ 5836 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5837 PetscFunctionReturn(0); 5838 } 5839 5840 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5841 { 5842 DMLabel depthLabel; 5843 PetscSection clSection; 5844 IS clPoints; 5845 PetscScalar *array; 5846 const PetscScalar *vArray; 5847 PetscInt *points = NULL; 5848 const PetscInt *clp, *perm = NULL; 5849 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5850 PetscErrorCode ierr; 5851 5852 PetscFunctionBeginHot; 5853 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5854 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5855 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5856 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5857 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5858 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5859 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5860 if (mdepth == 1 && numFields < 2) { 5861 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5862 PetscFunctionReturn(0); 5863 } 5864 /* Get points */ 5865 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5866 for (clsize=0,p=0; p<Np; p++) { 5867 PetscInt dof; 5868 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5869 clsize += dof; 5870 } 5871 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5872 /* Filter points */ 5873 for (p = 0; p < numPoints*2; p += 2) { 5874 PetscInt dep; 5875 5876 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5877 if (dep != depth) continue; 5878 points[Np*2+0] = points[p]; 5879 points[Np*2+1] = points[p+1]; 5880 ++Np; 5881 } 5882 /* Get array */ 5883 if (!values || !*values) { 5884 PetscInt asize = 0, dof; 5885 5886 for (p = 0; p < Np*2; p += 2) { 5887 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5888 asize += dof; 5889 } 5890 if (!values) { 5891 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5892 if (csize) *csize = asize; 5893 PetscFunctionReturn(0); 5894 } 5895 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5896 } else { 5897 array = *values; 5898 } 5899 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5900 /* Get values */ 5901 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5902 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5903 /* Cleanup points */ 5904 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5905 /* Cleanup array */ 5906 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5907 if (!*values) { 5908 if (csize) *csize = size; 5909 *values = array; 5910 } else { 5911 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5912 *csize = size; 5913 } 5914 PetscFunctionReturn(0); 5915 } 5916 5917 /*@C 5918 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5919 5920 Not collective 5921 5922 Input Parameters: 5923 + dm - The DM 5924 . section - The section describing the layout in v, or NULL to use the default section 5925 . v - The local vector 5926 . point - The point in the DM 5927 . csize - The number of values in the closure, or NULL 5928 - values - The array of values, which is a borrowed array and should not be freed 5929 5930 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5931 5932 Fortran Notes: 5933 Since it returns an array, this routine is only available in Fortran 90, and you must 5934 include petsc.h90 in your code. 5935 5936 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5937 5938 Level: intermediate 5939 5940 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5941 @*/ 5942 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5943 { 5944 PetscInt size = 0; 5945 PetscErrorCode ierr; 5946 5947 PetscFunctionBegin; 5948 /* Should work without recalculating size */ 5949 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5950 *values = NULL; 5951 PetscFunctionReturn(0); 5952 } 5953 5954 static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 5955 static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5956 5957 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[]) 5958 { 5959 PetscInt cdof; /* The number of constraints on this point */ 5960 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5961 PetscScalar *a; 5962 PetscInt off, cind = 0, k; 5963 PetscErrorCode ierr; 5964 5965 PetscFunctionBegin; 5966 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5967 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5968 a = &array[off]; 5969 if (!cdof || setBC) { 5970 if (clperm) { 5971 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5972 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5973 } else { 5974 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5975 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5976 } 5977 } else { 5978 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5979 if (clperm) { 5980 if (perm) {for (k = 0; k < dof; ++k) { 5981 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5982 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5983 } 5984 } else { 5985 for (k = 0; k < dof; ++k) { 5986 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5987 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5988 } 5989 } 5990 } else { 5991 if (perm) { 5992 for (k = 0; k < dof; ++k) { 5993 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5994 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5995 } 5996 } else { 5997 for (k = 0; k < dof; ++k) { 5998 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5999 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 6000 } 6001 } 6002 } 6003 } 6004 PetscFunctionReturn(0); 6005 } 6006 6007 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[]) 6008 { 6009 PetscInt cdof; /* The number of constraints on this point */ 6010 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6011 PetscScalar *a; 6012 PetscInt off, cind = 0, k; 6013 PetscErrorCode ierr; 6014 6015 PetscFunctionBegin; 6016 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6017 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6018 a = &array[off]; 6019 if (cdof) { 6020 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6021 if (clperm) { 6022 if (perm) { 6023 for (k = 0; k < dof; ++k) { 6024 if ((cind < cdof) && (k == cdofs[cind])) { 6025 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6026 cind++; 6027 } 6028 } 6029 } else { 6030 for (k = 0; k < dof; ++k) { 6031 if ((cind < cdof) && (k == cdofs[cind])) { 6032 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 6033 cind++; 6034 } 6035 } 6036 } 6037 } else { 6038 if (perm) { 6039 for (k = 0; k < dof; ++k) { 6040 if ((cind < cdof) && (k == cdofs[cind])) { 6041 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 6042 cind++; 6043 } 6044 } 6045 } else { 6046 for (k = 0; k < dof; ++k) { 6047 if ((cind < cdof) && (k == cdofs[cind])) { 6048 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 6049 cind++; 6050 } 6051 } 6052 } 6053 } 6054 } 6055 PetscFunctionReturn(0); 6056 } 6057 6058 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[]) 6059 { 6060 PetscScalar *a; 6061 PetscInt fdof, foff, fcdof, foffset = *offset; 6062 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6063 PetscInt cind = 0, b; 6064 PetscErrorCode ierr; 6065 6066 PetscFunctionBegin; 6067 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6068 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6069 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6070 a = &array[foff]; 6071 if (!fcdof || setBC) { 6072 if (clperm) { 6073 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 6074 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6075 } else { 6076 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 6077 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6078 } 6079 } else { 6080 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6081 if (clperm) { 6082 if (perm) { 6083 for (b = 0; b < fdof; b++) { 6084 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6085 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6086 } 6087 } else { 6088 for (b = 0; b < fdof; b++) { 6089 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6090 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6091 } 6092 } 6093 } else { 6094 if (perm) { 6095 for (b = 0; b < fdof; b++) { 6096 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6097 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6098 } 6099 } else { 6100 for (b = 0; b < fdof; b++) { 6101 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6102 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6103 } 6104 } 6105 } 6106 } 6107 *offset += fdof; 6108 PetscFunctionReturn(0); 6109 } 6110 6111 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[]) 6112 { 6113 PetscScalar *a; 6114 PetscInt fdof, foff, fcdof, foffset = *offset; 6115 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6116 PetscInt Nc, cind = 0, ncind = 0, b; 6117 PetscBool ncSet, fcSet; 6118 PetscErrorCode ierr; 6119 6120 PetscFunctionBegin; 6121 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 6122 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6123 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6124 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6125 a = &array[foff]; 6126 if (fcdof) { 6127 /* We just override fcdof and fcdofs with Ncc and comps */ 6128 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6129 if (clperm) { 6130 if (perm) { 6131 if (comps) { 6132 for (b = 0; b < fdof; b++) { 6133 ncSet = fcSet = PETSC_FALSE; 6134 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6135 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6136 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6137 } 6138 } else { 6139 for (b = 0; b < fdof; b++) { 6140 if ((cind < fcdof) && (b == fcdofs[cind])) { 6141 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6142 ++cind; 6143 } 6144 } 6145 } 6146 } else { 6147 if (comps) { 6148 for (b = 0; b < fdof; b++) { 6149 ncSet = fcSet = PETSC_FALSE; 6150 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6151 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6152 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6153 } 6154 } else { 6155 for (b = 0; b < fdof; b++) { 6156 if ((cind < fcdof) && (b == fcdofs[cind])) { 6157 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6158 ++cind; 6159 } 6160 } 6161 } 6162 } 6163 } else { 6164 if (perm) { 6165 if (comps) { 6166 for (b = 0; b < fdof; b++) { 6167 ncSet = fcSet = PETSC_FALSE; 6168 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6169 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6170 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6171 } 6172 } else { 6173 for (b = 0; b < fdof; b++) { 6174 if ((cind < fcdof) && (b == fcdofs[cind])) { 6175 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6176 ++cind; 6177 } 6178 } 6179 } 6180 } else { 6181 if (comps) { 6182 for (b = 0; b < fdof; b++) { 6183 ncSet = fcSet = PETSC_FALSE; 6184 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6185 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6186 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6187 } 6188 } else { 6189 for (b = 0; b < fdof; b++) { 6190 if ((cind < fcdof) && (b == fcdofs[cind])) { 6191 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6192 ++cind; 6193 } 6194 } 6195 } 6196 } 6197 } 6198 } 6199 *offset += fdof; 6200 PetscFunctionReturn(0); 6201 } 6202 6203 static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6204 { 6205 PetscScalar *array; 6206 const PetscInt *cone, *coneO; 6207 PetscInt pStart, pEnd, p, numPoints, off, dof; 6208 PetscErrorCode ierr; 6209 6210 PetscFunctionBeginHot; 6211 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6212 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6213 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6214 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6215 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6216 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6217 const PetscInt cp = !p ? point : cone[p-1]; 6218 const PetscInt o = !p ? 0 : coneO[p-1]; 6219 6220 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 6221 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6222 /* ADD_VALUES */ 6223 { 6224 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6225 PetscScalar *a; 6226 PetscInt cdof, coff, cind = 0, k; 6227 6228 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 6229 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 6230 a = &array[coff]; 6231 if (!cdof) { 6232 if (o >= 0) { 6233 for (k = 0; k < dof; ++k) { 6234 a[k] += values[off+k]; 6235 } 6236 } else { 6237 for (k = 0; k < dof; ++k) { 6238 a[k] += values[off+dof-k-1]; 6239 } 6240 } 6241 } else { 6242 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6243 if (o >= 0) { 6244 for (k = 0; k < dof; ++k) { 6245 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6246 a[k] += values[off+k]; 6247 } 6248 } else { 6249 for (k = 0; k < dof; ++k) { 6250 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6251 a[k] += values[off+dof-k-1]; 6252 } 6253 } 6254 } 6255 } 6256 } 6257 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6258 PetscFunctionReturn(0); 6259 } 6260 6261 /*@C 6262 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6263 6264 Not collective 6265 6266 Input Parameters: 6267 + dm - The DM 6268 . section - The section describing the layout in v, or NULL to use the default section 6269 . v - The local vector 6270 . point - The point in the DM 6271 . values - The array of values 6272 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6273 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6274 6275 Fortran Notes: 6276 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6277 6278 Level: intermediate 6279 6280 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6281 @*/ 6282 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6283 { 6284 PetscSection clSection; 6285 IS clPoints; 6286 PetscScalar *array; 6287 PetscInt *points = NULL; 6288 const PetscInt *clp, *clperm = NULL; 6289 PetscInt depth, numFields, numPoints, p, clsize; 6290 PetscErrorCode ierr; 6291 6292 PetscFunctionBeginHot; 6293 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6294 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6295 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6296 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6297 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6298 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6299 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6300 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6301 PetscFunctionReturn(0); 6302 } 6303 /* Get points */ 6304 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6305 for (clsize=0,p=0; p<numPoints; p++) { 6306 PetscInt dof; 6307 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6308 clsize += dof; 6309 } 6310 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6311 /* Get array */ 6312 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6313 /* Get values */ 6314 if (numFields > 0) { 6315 PetscInt offset = 0, f; 6316 for (f = 0; f < numFields; ++f) { 6317 const PetscInt **perms = NULL; 6318 const PetscScalar **flips = NULL; 6319 6320 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6321 switch (mode) { 6322 case INSERT_VALUES: 6323 for (p = 0; p < numPoints; p++) { 6324 const PetscInt point = points[2*p]; 6325 const PetscInt *perm = perms ? perms[p] : NULL; 6326 const PetscScalar *flip = flips ? flips[p] : NULL; 6327 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6328 } break; 6329 case INSERT_ALL_VALUES: 6330 for (p = 0; p < numPoints; p++) { 6331 const PetscInt point = points[2*p]; 6332 const PetscInt *perm = perms ? perms[p] : NULL; 6333 const PetscScalar *flip = flips ? flips[p] : NULL; 6334 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6335 } break; 6336 case INSERT_BC_VALUES: 6337 for (p = 0; p < numPoints; p++) { 6338 const PetscInt point = points[2*p]; 6339 const PetscInt *perm = perms ? perms[p] : NULL; 6340 const PetscScalar *flip = flips ? flips[p] : NULL; 6341 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6342 } break; 6343 case ADD_VALUES: 6344 for (p = 0; p < numPoints; p++) { 6345 const PetscInt point = points[2*p]; 6346 const PetscInt *perm = perms ? perms[p] : NULL; 6347 const PetscScalar *flip = flips ? flips[p] : NULL; 6348 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6349 } break; 6350 case ADD_ALL_VALUES: 6351 for (p = 0; p < numPoints; p++) { 6352 const PetscInt point = points[2*p]; 6353 const PetscInt *perm = perms ? perms[p] : NULL; 6354 const PetscScalar *flip = flips ? flips[p] : NULL; 6355 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6356 } break; 6357 case ADD_BC_VALUES: 6358 for (p = 0; p < numPoints; p++) { 6359 const PetscInt point = points[2*p]; 6360 const PetscInt *perm = perms ? perms[p] : NULL; 6361 const PetscScalar *flip = flips ? flips[p] : NULL; 6362 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6363 } break; 6364 default: 6365 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6366 } 6367 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6368 } 6369 } else { 6370 PetscInt dof, off; 6371 const PetscInt **perms = NULL; 6372 const PetscScalar **flips = NULL; 6373 6374 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6375 switch (mode) { 6376 case INSERT_VALUES: 6377 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6378 const PetscInt point = points[2*p]; 6379 const PetscInt *perm = perms ? perms[p] : NULL; 6380 const PetscScalar *flip = flips ? flips[p] : NULL; 6381 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6382 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6383 } break; 6384 case INSERT_ALL_VALUES: 6385 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6386 const PetscInt point = points[2*p]; 6387 const PetscInt *perm = perms ? perms[p] : NULL; 6388 const PetscScalar *flip = flips ? flips[p] : NULL; 6389 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6390 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6391 } break; 6392 case INSERT_BC_VALUES: 6393 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6394 const PetscInt point = points[2*p]; 6395 const PetscInt *perm = perms ? perms[p] : NULL; 6396 const PetscScalar *flip = flips ? flips[p] : NULL; 6397 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6398 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6399 } break; 6400 case ADD_VALUES: 6401 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6402 const PetscInt point = points[2*p]; 6403 const PetscInt *perm = perms ? perms[p] : NULL; 6404 const PetscScalar *flip = flips ? flips[p] : NULL; 6405 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6406 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6407 } break; 6408 case ADD_ALL_VALUES: 6409 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6410 const PetscInt point = points[2*p]; 6411 const PetscInt *perm = perms ? perms[p] : NULL; 6412 const PetscScalar *flip = flips ? flips[p] : NULL; 6413 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6414 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6415 } break; 6416 case ADD_BC_VALUES: 6417 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6418 const PetscInt point = points[2*p]; 6419 const PetscInt *perm = perms ? perms[p] : NULL; 6420 const PetscScalar *flip = flips ? flips[p] : NULL; 6421 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6422 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6423 } break; 6424 default: 6425 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6426 } 6427 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6428 } 6429 /* Cleanup points */ 6430 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6431 /* Cleanup array */ 6432 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6433 PetscFunctionReturn(0); 6434 } 6435 6436 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6437 static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6438 { 6439 PetscFunctionBegin; 6440 if (label) { 6441 PetscInt val, fdof; 6442 PetscErrorCode ierr; 6443 6444 /* There is a problem with this: 6445 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6446 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6447 Thus I am only going to check val != -1, not val != labelId 6448 */ 6449 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6450 if (val < 0) { 6451 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6452 *offset += fdof; 6453 PetscFunctionReturn(1); 6454 } 6455 } 6456 PetscFunctionReturn(0); 6457 } 6458 6459 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6460 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt labelId, const PetscScalar values[], InsertMode mode) 6461 { 6462 PetscSection clSection; 6463 IS clPoints; 6464 PetscScalar *array; 6465 PetscInt *points = NULL; 6466 const PetscInt *clp; 6467 PetscInt numFields, numPoints, p; 6468 PetscInt offset = 0, f; 6469 PetscErrorCode ierr; 6470 6471 PetscFunctionBeginHot; 6472 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6473 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6474 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6475 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6476 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6477 /* Get points */ 6478 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6479 /* Get array */ 6480 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6481 /* Get values */ 6482 for (f = 0; f < numFields; ++f) { 6483 const PetscInt **perms = NULL; 6484 const PetscScalar **flips = NULL; 6485 6486 if (!fieldActive[f]) { 6487 for (p = 0; p < numPoints*2; p += 2) { 6488 PetscInt fdof; 6489 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6490 offset += fdof; 6491 } 6492 continue; 6493 } 6494 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6495 switch (mode) { 6496 case INSERT_VALUES: 6497 for (p = 0; p < numPoints; p++) { 6498 const PetscInt point = points[2*p]; 6499 const PetscInt *perm = perms ? perms[p] : NULL; 6500 const PetscScalar *flip = flips ? flips[p] : NULL; 6501 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6502 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6503 } break; 6504 case INSERT_ALL_VALUES: 6505 for (p = 0; p < numPoints; p++) { 6506 const PetscInt point = points[2*p]; 6507 const PetscInt *perm = perms ? perms[p] : NULL; 6508 const PetscScalar *flip = flips ? flips[p] : NULL; 6509 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6510 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6511 } break; 6512 case INSERT_BC_VALUES: 6513 for (p = 0; p < numPoints; p++) { 6514 const PetscInt point = points[2*p]; 6515 const PetscInt *perm = perms ? perms[p] : NULL; 6516 const PetscScalar *flip = flips ? flips[p] : NULL; 6517 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6518 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6519 } break; 6520 case ADD_VALUES: 6521 for (p = 0; p < numPoints; p++) { 6522 const PetscInt point = points[2*p]; 6523 const PetscInt *perm = perms ? perms[p] : NULL; 6524 const PetscScalar *flip = flips ? flips[p] : NULL; 6525 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6526 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6527 } break; 6528 case ADD_ALL_VALUES: 6529 for (p = 0; p < numPoints; p++) { 6530 const PetscInt point = points[2*p]; 6531 const PetscInt *perm = perms ? perms[p] : NULL; 6532 const PetscScalar *flip = flips ? flips[p] : NULL; 6533 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6534 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6535 } break; 6536 default: 6537 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6538 } 6539 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6540 } 6541 /* Cleanup points */ 6542 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6543 /* Cleanup array */ 6544 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6545 PetscFunctionReturn(0); 6546 } 6547 6548 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6549 { 6550 PetscMPIInt rank; 6551 PetscInt i, j; 6552 PetscErrorCode ierr; 6553 6554 PetscFunctionBegin; 6555 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6556 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6557 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6558 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6559 numCIndices = numCIndices ? numCIndices : numRIndices; 6560 if (!values) PetscFunctionReturn(0); 6561 for (i = 0; i < numRIndices; i++) { 6562 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6563 for (j = 0; j < numCIndices; j++) { 6564 #if defined(PETSC_USE_COMPLEX) 6565 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6566 #else 6567 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6568 #endif 6569 } 6570 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6571 } 6572 PetscFunctionReturn(0); 6573 } 6574 6575 /* 6576 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6577 6578 Input Parameters: 6579 + section - The section for this data layout 6580 . islocal - Is the section (and thus indices being requested) local or global? 6581 . point - The point contributing dofs with these indices 6582 . off - The global offset of this point 6583 . loff - The local offset of each field 6584 . setBC - The flag determining whether to include indices of boundary values 6585 . perm - A permutation of the dofs on this point, or NULL 6586 - indperm - A permutation of the entire indices array, or NULL 6587 6588 Output Parameter: 6589 . indices - Indices for dofs on this point 6590 6591 Level: developer 6592 6593 Note: The indices could be local or global, depending on the value of 'off'. 6594 */ 6595 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6596 { 6597 PetscInt dof; /* The number of unknowns on this point */ 6598 PetscInt cdof; /* The number of constraints on this point */ 6599 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6600 PetscInt cind = 0, k; 6601 PetscErrorCode ierr; 6602 6603 PetscFunctionBegin; 6604 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6605 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6606 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6607 if (!cdof || setBC) { 6608 for (k = 0; k < dof; ++k) { 6609 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6610 const PetscInt ind = indperm ? indperm[preind] : preind; 6611 6612 indices[ind] = off + k; 6613 } 6614 } else { 6615 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6616 for (k = 0; k < dof; ++k) { 6617 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6618 const PetscInt ind = indperm ? indperm[preind] : preind; 6619 6620 if ((cind < cdof) && (k == cdofs[cind])) { 6621 /* Insert check for returning constrained indices */ 6622 indices[ind] = -(off+k+1); 6623 ++cind; 6624 } else { 6625 indices[ind] = off + k - (islocal ? 0 : cind); 6626 } 6627 } 6628 } 6629 *loff += dof; 6630 PetscFunctionReturn(0); 6631 } 6632 6633 /* 6634 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6635 6636 Input Parameters: 6637 + section - a section (global or local) 6638 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6639 . point - point within section 6640 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6641 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6642 . setBC - identify constrained (boundary condition) points via involution. 6643 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6644 . permsoff - offset 6645 - indperm - index permutation 6646 6647 Output Parameter: 6648 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6649 . indices - array to hold indices (as defined by section) of each dof associated with point 6650 6651 Notes: 6652 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6653 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6654 in the local vector. 6655 6656 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6657 significant). It is invalid to call with a global section and setBC=true. 6658 6659 Developer Note: 6660 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6661 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6662 offset could be obtained from the section instead of passing it explicitly as we do now. 6663 6664 Example: 6665 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6666 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6667 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6668 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. 6669 6670 Level: developer 6671 */ 6672 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[]) 6673 { 6674 PetscInt numFields, foff, f; 6675 PetscErrorCode ierr; 6676 6677 PetscFunctionBegin; 6678 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6679 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6680 for (f = 0, foff = 0; f < numFields; ++f) { 6681 PetscInt fdof, cfdof; 6682 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6683 PetscInt cind = 0, b; 6684 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6685 6686 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6687 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6688 if (!cfdof || setBC) { 6689 for (b = 0; b < fdof; ++b) { 6690 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6691 const PetscInt ind = indperm ? indperm[preind] : preind; 6692 6693 indices[ind] = off+foff+b; 6694 } 6695 } else { 6696 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6697 for (b = 0; b < fdof; ++b) { 6698 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6699 const PetscInt ind = indperm ? indperm[preind] : preind; 6700 6701 if ((cind < cfdof) && (b == fcdofs[cind])) { 6702 indices[ind] = -(off+foff+b+1); 6703 ++cind; 6704 } else { 6705 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6706 } 6707 } 6708 } 6709 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6710 foffs[f] += fdof; 6711 } 6712 PetscFunctionReturn(0); 6713 } 6714 6715 /* 6716 This version believes the globalSection offsets for each field, rather than just the point offset 6717 6718 . foffs - The offset into 'indices' for each field, since it is segregated by field 6719 6720 Notes: 6721 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6722 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6723 */ 6724 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6725 { 6726 PetscInt numFields, foff, f; 6727 PetscErrorCode ierr; 6728 6729 PetscFunctionBegin; 6730 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6731 for (f = 0; f < numFields; ++f) { 6732 PetscInt fdof, cfdof; 6733 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6734 PetscInt cind = 0, b; 6735 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6736 6737 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6738 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6739 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6740 if (!cfdof) { 6741 for (b = 0; b < fdof; ++b) { 6742 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6743 const PetscInt ind = indperm ? indperm[preind] : preind; 6744 6745 indices[ind] = foff+b; 6746 } 6747 } else { 6748 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6749 for (b = 0; b < fdof; ++b) { 6750 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6751 const PetscInt ind = indperm ? indperm[preind] : preind; 6752 6753 if ((cind < cfdof) && (b == fcdofs[cind])) { 6754 indices[ind] = -(foff+b+1); 6755 ++cind; 6756 } else { 6757 indices[ind] = foff+b-cind; 6758 } 6759 } 6760 } 6761 foffs[f] += fdof; 6762 } 6763 PetscFunctionReturn(0); 6764 } 6765 6766 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) 6767 { 6768 Mat cMat; 6769 PetscSection aSec, cSec; 6770 IS aIS; 6771 PetscInt aStart = -1, aEnd = -1; 6772 const PetscInt *anchors; 6773 PetscInt numFields, f, p, q, newP = 0; 6774 PetscInt newNumPoints = 0, newNumIndices = 0; 6775 PetscInt *newPoints, *indices, *newIndices; 6776 PetscInt maxAnchor, maxDof; 6777 PetscInt newOffsets[32]; 6778 PetscInt *pointMatOffsets[32]; 6779 PetscInt *newPointOffsets[32]; 6780 PetscScalar *pointMat[32]; 6781 PetscScalar *newValues=NULL,*tmpValues; 6782 PetscBool anyConstrained = PETSC_FALSE; 6783 PetscErrorCode ierr; 6784 6785 PetscFunctionBegin; 6786 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6787 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6788 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6789 6790 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6791 /* if there are point-to-point constraints */ 6792 if (aSec) { 6793 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6794 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6795 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6796 /* figure out how many points are going to be in the new element matrix 6797 * (we allow double counting, because it's all just going to be summed 6798 * into the global matrix anyway) */ 6799 for (p = 0; p < 2*numPoints; p+=2) { 6800 PetscInt b = points[p]; 6801 PetscInt bDof = 0, bSecDof; 6802 6803 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6804 if (!bSecDof) { 6805 continue; 6806 } 6807 if (b >= aStart && b < aEnd) { 6808 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6809 } 6810 if (bDof) { 6811 /* this point is constrained */ 6812 /* it is going to be replaced by its anchors */ 6813 PetscInt bOff, q; 6814 6815 anyConstrained = PETSC_TRUE; 6816 newNumPoints += bDof; 6817 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6818 for (q = 0; q < bDof; q++) { 6819 PetscInt a = anchors[bOff + q]; 6820 PetscInt aDof; 6821 6822 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6823 newNumIndices += aDof; 6824 for (f = 0; f < numFields; ++f) { 6825 PetscInt fDof; 6826 6827 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6828 newOffsets[f+1] += fDof; 6829 } 6830 } 6831 } 6832 else { 6833 /* this point is not constrained */ 6834 newNumPoints++; 6835 newNumIndices += bSecDof; 6836 for (f = 0; f < numFields; ++f) { 6837 PetscInt fDof; 6838 6839 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6840 newOffsets[f+1] += fDof; 6841 } 6842 } 6843 } 6844 } 6845 if (!anyConstrained) { 6846 if (outNumPoints) *outNumPoints = 0; 6847 if (outNumIndices) *outNumIndices = 0; 6848 if (outPoints) *outPoints = NULL; 6849 if (outValues) *outValues = NULL; 6850 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6851 PetscFunctionReturn(0); 6852 } 6853 6854 if (outNumPoints) *outNumPoints = newNumPoints; 6855 if (outNumIndices) *outNumIndices = newNumIndices; 6856 6857 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6858 6859 if (!outPoints && !outValues) { 6860 if (offsets) { 6861 for (f = 0; f <= numFields; f++) { 6862 offsets[f] = newOffsets[f]; 6863 } 6864 } 6865 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6866 PetscFunctionReturn(0); 6867 } 6868 6869 PetscCheckFalse(numFields && newOffsets[numFields] != newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6870 6871 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat, NULL);CHKERRQ(ierr); 6872 6873 /* workspaces */ 6874 if (numFields) { 6875 for (f = 0; f < numFields; f++) { 6876 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6877 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6878 } 6879 } 6880 else { 6881 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6882 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6883 } 6884 6885 /* get workspaces for the point-to-point matrices */ 6886 if (numFields) { 6887 PetscInt totalOffset, totalMatOffset; 6888 6889 for (p = 0; p < numPoints; p++) { 6890 PetscInt b = points[2*p]; 6891 PetscInt bDof = 0, bSecDof; 6892 6893 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6894 if (!bSecDof) { 6895 for (f = 0; f < numFields; f++) { 6896 newPointOffsets[f][p + 1] = 0; 6897 pointMatOffsets[f][p + 1] = 0; 6898 } 6899 continue; 6900 } 6901 if (b >= aStart && b < aEnd) { 6902 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6903 } 6904 if (bDof) { 6905 for (f = 0; f < numFields; f++) { 6906 PetscInt fDof, q, bOff, allFDof = 0; 6907 6908 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6909 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6910 for (q = 0; q < bDof; q++) { 6911 PetscInt a = anchors[bOff + q]; 6912 PetscInt aFDof; 6913 6914 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6915 allFDof += aFDof; 6916 } 6917 newPointOffsets[f][p+1] = allFDof; 6918 pointMatOffsets[f][p+1] = fDof * allFDof; 6919 } 6920 } 6921 else { 6922 for (f = 0; f < numFields; f++) { 6923 PetscInt fDof; 6924 6925 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6926 newPointOffsets[f][p+1] = fDof; 6927 pointMatOffsets[f][p+1] = 0; 6928 } 6929 } 6930 } 6931 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6932 newPointOffsets[f][0] = totalOffset; 6933 pointMatOffsets[f][0] = totalMatOffset; 6934 for (p = 0; p < numPoints; p++) { 6935 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6936 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6937 } 6938 totalOffset = newPointOffsets[f][numPoints]; 6939 totalMatOffset = pointMatOffsets[f][numPoints]; 6940 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6941 } 6942 } 6943 else { 6944 for (p = 0; p < numPoints; p++) { 6945 PetscInt b = points[2*p]; 6946 PetscInt bDof = 0, bSecDof; 6947 6948 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6949 if (!bSecDof) { 6950 newPointOffsets[0][p + 1] = 0; 6951 pointMatOffsets[0][p + 1] = 0; 6952 continue; 6953 } 6954 if (b >= aStart && b < aEnd) { 6955 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6956 } 6957 if (bDof) { 6958 PetscInt bOff, q, allDof = 0; 6959 6960 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6961 for (q = 0; q < bDof; q++) { 6962 PetscInt a = anchors[bOff + q], aDof; 6963 6964 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6965 allDof += aDof; 6966 } 6967 newPointOffsets[0][p+1] = allDof; 6968 pointMatOffsets[0][p+1] = bSecDof * allDof; 6969 } 6970 else { 6971 newPointOffsets[0][p+1] = bSecDof; 6972 pointMatOffsets[0][p+1] = 0; 6973 } 6974 } 6975 newPointOffsets[0][0] = 0; 6976 pointMatOffsets[0][0] = 0; 6977 for (p = 0; p < numPoints; p++) { 6978 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6979 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6980 } 6981 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6982 } 6983 6984 /* output arrays */ 6985 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6986 6987 /* get the point-to-point matrices; construct newPoints */ 6988 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6989 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6990 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6991 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6992 if (numFields) { 6993 for (p = 0, newP = 0; p < numPoints; p++) { 6994 PetscInt b = points[2*p]; 6995 PetscInt o = points[2*p+1]; 6996 PetscInt bDof = 0, bSecDof; 6997 6998 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6999 if (!bSecDof) { 7000 continue; 7001 } 7002 if (b >= aStart && b < aEnd) { 7003 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 7004 } 7005 if (bDof) { 7006 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 7007 7008 fStart[0] = 0; 7009 fEnd[0] = 0; 7010 for (f = 0; f < numFields; f++) { 7011 PetscInt fDof; 7012 7013 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 7014 fStart[f+1] = fStart[f] + fDof; 7015 fEnd[f+1] = fStart[f+1]; 7016 } 7017 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 7018 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 7019 7020 fAnchorStart[0] = 0; 7021 fAnchorEnd[0] = 0; 7022 for (f = 0; f < numFields; f++) { 7023 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7024 7025 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 7026 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 7027 } 7028 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 7029 for (q = 0; q < bDof; q++) { 7030 PetscInt a = anchors[bOff + q], aOff; 7031 7032 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7033 newPoints[2*(newP + q)] = a; 7034 newPoints[2*(newP + q) + 1] = 0; 7035 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7036 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 7037 } 7038 newP += bDof; 7039 7040 if (outValues) { 7041 /* get the point-to-point submatrix */ 7042 for (f = 0; f < numFields; f++) { 7043 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 7044 } 7045 } 7046 } 7047 else { 7048 newPoints[2 * newP] = b; 7049 newPoints[2 * newP + 1] = o; 7050 newP++; 7051 } 7052 } 7053 } else { 7054 for (p = 0; p < numPoints; p++) { 7055 PetscInt b = points[2*p]; 7056 PetscInt o = points[2*p+1]; 7057 PetscInt bDof = 0, bSecDof; 7058 7059 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 7060 if (!bSecDof) { 7061 continue; 7062 } 7063 if (b >= aStart && b < aEnd) { 7064 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 7065 } 7066 if (bDof) { 7067 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7068 7069 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 7070 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 7071 7072 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 7073 for (q = 0; q < bDof; q++) { 7074 PetscInt a = anchors[bOff + q], aOff; 7075 7076 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7077 7078 newPoints[2*(newP + q)] = a; 7079 newPoints[2*(newP + q) + 1] = 0; 7080 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7081 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 7082 } 7083 newP += bDof; 7084 7085 /* get the point-to-point submatrix */ 7086 if (outValues) { 7087 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 7088 } 7089 } 7090 else { 7091 newPoints[2 * newP] = b; 7092 newPoints[2 * newP + 1] = o; 7093 newP++; 7094 } 7095 } 7096 } 7097 7098 if (outValues) { 7099 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7100 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 7101 /* multiply constraints on the right */ 7102 if (numFields) { 7103 for (f = 0; f < numFields; f++) { 7104 PetscInt oldOff = offsets[f]; 7105 7106 for (p = 0; p < numPoints; p++) { 7107 PetscInt cStart = newPointOffsets[f][p]; 7108 PetscInt b = points[2 * p]; 7109 PetscInt c, r, k; 7110 PetscInt dof; 7111 7112 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7113 if (!dof) { 7114 continue; 7115 } 7116 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7117 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7118 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7119 7120 for (r = 0; r < numIndices; r++) { 7121 for (c = 0; c < nCols; c++) { 7122 for (k = 0; k < dof; k++) { 7123 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7124 } 7125 } 7126 } 7127 } 7128 else { 7129 /* copy this column as is */ 7130 for (r = 0; r < numIndices; r++) { 7131 for (c = 0; c < dof; c++) { 7132 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7133 } 7134 } 7135 } 7136 oldOff += dof; 7137 } 7138 } 7139 } 7140 else { 7141 PetscInt oldOff = 0; 7142 for (p = 0; p < numPoints; p++) { 7143 PetscInt cStart = newPointOffsets[0][p]; 7144 PetscInt b = points[2 * p]; 7145 PetscInt c, r, k; 7146 PetscInt dof; 7147 7148 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7149 if (!dof) { 7150 continue; 7151 } 7152 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7153 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7154 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7155 7156 for (r = 0; r < numIndices; r++) { 7157 for (c = 0; c < nCols; c++) { 7158 for (k = 0; k < dof; k++) { 7159 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7160 } 7161 } 7162 } 7163 } 7164 else { 7165 /* copy this column as is */ 7166 for (r = 0; r < numIndices; r++) { 7167 for (c = 0; c < dof; c++) { 7168 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7169 } 7170 } 7171 } 7172 oldOff += dof; 7173 } 7174 } 7175 7176 if (multiplyLeft) { 7177 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 7178 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 7179 /* multiply constraints transpose on the left */ 7180 if (numFields) { 7181 for (f = 0; f < numFields; f++) { 7182 PetscInt oldOff = offsets[f]; 7183 7184 for (p = 0; p < numPoints; p++) { 7185 PetscInt rStart = newPointOffsets[f][p]; 7186 PetscInt b = points[2 * p]; 7187 PetscInt c, r, k; 7188 PetscInt dof; 7189 7190 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7191 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7192 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7193 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7194 7195 for (r = 0; r < nRows; r++) { 7196 for (c = 0; c < newNumIndices; c++) { 7197 for (k = 0; k < dof; k++) { 7198 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7199 } 7200 } 7201 } 7202 } 7203 else { 7204 /* copy this row as is */ 7205 for (r = 0; r < dof; r++) { 7206 for (c = 0; c < newNumIndices; c++) { 7207 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7208 } 7209 } 7210 } 7211 oldOff += dof; 7212 } 7213 } 7214 } 7215 else { 7216 PetscInt oldOff = 0; 7217 7218 for (p = 0; p < numPoints; p++) { 7219 PetscInt rStart = newPointOffsets[0][p]; 7220 PetscInt b = points[2 * p]; 7221 PetscInt c, r, k; 7222 PetscInt dof; 7223 7224 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7225 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7226 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7227 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7228 7229 for (r = 0; r < nRows; r++) { 7230 for (c = 0; c < newNumIndices; c++) { 7231 for (k = 0; k < dof; k++) { 7232 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7233 } 7234 } 7235 } 7236 } 7237 else { 7238 /* copy this row as is */ 7239 for (r = 0; r < dof; r++) { 7240 for (c = 0; c < newNumIndices; c++) { 7241 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7242 } 7243 } 7244 } 7245 oldOff += dof; 7246 } 7247 } 7248 7249 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7250 } 7251 else { 7252 newValues = tmpValues; 7253 } 7254 } 7255 7256 /* clean up */ 7257 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7258 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7259 7260 if (numFields) { 7261 for (f = 0; f < numFields; f++) { 7262 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7263 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7264 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7265 } 7266 } 7267 else { 7268 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7269 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7270 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7271 } 7272 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7273 7274 /* output */ 7275 if (outPoints) { 7276 *outPoints = newPoints; 7277 } 7278 else { 7279 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7280 } 7281 if (outValues) { 7282 *outValues = newValues; 7283 } 7284 for (f = 0; f <= numFields; f++) { 7285 offsets[f] = newOffsets[f]; 7286 } 7287 PetscFunctionReturn(0); 7288 } 7289 7290 /*@C 7291 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7292 7293 Not collective 7294 7295 Input Parameters: 7296 + dm - The DM 7297 . section - The PetscSection describing the points (a local section) 7298 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7299 . point - The point defining the closure 7300 - useClPerm - Use the closure point permutation if available 7301 7302 Output Parameters: 7303 + numIndices - The number of dof indices in the closure of point with the input sections 7304 . indices - The dof indices 7305 . outOffsets - Array to write the field offsets into, or NULL 7306 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7307 7308 Notes: 7309 Must call DMPlexRestoreClosureIndices() to free allocated memory 7310 7311 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7312 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7313 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7314 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7315 indices (with the above semantics) are implied. 7316 7317 Level: advanced 7318 7319 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7320 @*/ 7321 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7322 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7323 { 7324 /* Closure ordering */ 7325 PetscSection clSection; 7326 IS clPoints; 7327 const PetscInt *clp; 7328 PetscInt *points; 7329 const PetscInt *clperm = NULL; 7330 /* Dof permutation and sign flips */ 7331 const PetscInt **perms[32] = {NULL}; 7332 const PetscScalar **flips[32] = {NULL}; 7333 PetscScalar *valCopy = NULL; 7334 /* Hanging node constraints */ 7335 PetscInt *pointsC = NULL; 7336 PetscScalar *valuesC = NULL; 7337 PetscInt NclC, NiC; 7338 7339 PetscInt *idx; 7340 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7341 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7342 PetscErrorCode ierr; 7343 7344 PetscFunctionBeginHot; 7345 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7346 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7347 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7348 if (numIndices) PetscValidPointer(numIndices, 6); 7349 if (indices) PetscValidPointer(indices, 7); 7350 if (outOffsets) PetscValidPointer(outOffsets, 8); 7351 if (values) PetscValidPointer(values, 9); 7352 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7353 PetscCheckFalse(Nf > 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7354 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7355 /* 1) Get points in closure */ 7356 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7357 if (useClPerm) { 7358 PetscInt depth, clsize; 7359 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7360 for (clsize=0,p=0; p<Ncl; p++) { 7361 PetscInt dof; 7362 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7363 clsize += dof; 7364 } 7365 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7366 } 7367 /* 2) Get number of indices on these points and field offsets from section */ 7368 for (p = 0; p < Ncl*2; p += 2) { 7369 PetscInt dof, fdof; 7370 7371 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7372 for (f = 0; f < Nf; ++f) { 7373 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7374 offsets[f+1] += fdof; 7375 } 7376 Ni += dof; 7377 } 7378 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7379 PetscCheckFalse(Nf && offsets[Nf] != Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7380 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7381 for (f = 0; f < PetscMax(1, Nf); ++f) { 7382 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7383 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7384 /* may need to apply sign changes to the element matrix */ 7385 if (values && flips[f]) { 7386 PetscInt foffset = offsets[f]; 7387 7388 for (p = 0; p < Ncl; ++p) { 7389 PetscInt pnt = points[2*p], fdof; 7390 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7391 7392 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7393 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7394 if (flip) { 7395 PetscInt i, j, k; 7396 7397 if (!valCopy) { 7398 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7399 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7400 *values = valCopy; 7401 } 7402 for (i = 0; i < fdof; ++i) { 7403 PetscScalar fval = flip[i]; 7404 7405 for (k = 0; k < Ni; ++k) { 7406 valCopy[Ni * (foffset + i) + k] *= fval; 7407 valCopy[Ni * k + (foffset + i)] *= fval; 7408 } 7409 } 7410 } 7411 foffset += fdof; 7412 } 7413 } 7414 } 7415 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7416 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7417 if (NclC) { 7418 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7419 for (f = 0; f < PetscMax(1, Nf); ++f) { 7420 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7421 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7422 } 7423 for (f = 0; f < PetscMax(1, Nf); ++f) { 7424 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7425 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7426 } 7427 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7428 Ncl = NclC; 7429 Ni = NiC; 7430 points = pointsC; 7431 if (values) *values = valuesC; 7432 } 7433 /* 5) Calculate indices */ 7434 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7435 if (Nf) { 7436 PetscInt idxOff; 7437 PetscBool useFieldOffsets; 7438 7439 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7440 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7441 if (useFieldOffsets) { 7442 for (p = 0; p < Ncl; ++p) { 7443 const PetscInt pnt = points[p*2]; 7444 7445 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7446 } 7447 } else { 7448 for (p = 0; p < Ncl; ++p) { 7449 const PetscInt pnt = points[p*2]; 7450 7451 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7452 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7453 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7454 * global section. */ 7455 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7456 } 7457 } 7458 } else { 7459 PetscInt off = 0, idxOff; 7460 7461 for (p = 0; p < Ncl; ++p) { 7462 const PetscInt pnt = points[p*2]; 7463 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7464 7465 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7466 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7467 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7468 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7469 } 7470 } 7471 /* 6) Cleanup */ 7472 for (f = 0; f < PetscMax(1, Nf); ++f) { 7473 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7474 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7475 } 7476 if (NclC) { 7477 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7478 } else { 7479 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7480 } 7481 7482 if (numIndices) *numIndices = Ni; 7483 if (indices) *indices = idx; 7484 PetscFunctionReturn(0); 7485 } 7486 7487 /*@C 7488 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7489 7490 Not collective 7491 7492 Input Parameters: 7493 + dm - The DM 7494 . section - The PetscSection describing the points (a local section) 7495 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7496 . point - The point defining the closure 7497 - useClPerm - Use the closure point permutation if available 7498 7499 Output Parameters: 7500 + numIndices - The number of dof indices in the closure of point with the input sections 7501 . indices - The dof indices 7502 . outOffsets - Array to write the field offsets into, or NULL 7503 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7504 7505 Notes: 7506 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7507 7508 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7509 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7510 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7511 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7512 indices (with the above semantics) are implied. 7513 7514 Level: advanced 7515 7516 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7517 @*/ 7518 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7519 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7520 { 7521 PetscErrorCode ierr; 7522 7523 PetscFunctionBegin; 7524 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7525 PetscValidPointer(indices, 7); 7526 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7527 PetscFunctionReturn(0); 7528 } 7529 7530 /*@C 7531 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7532 7533 Not collective 7534 7535 Input Parameters: 7536 + dm - The DM 7537 . section - The section describing the layout in v, or NULL to use the default section 7538 . globalSection - The section describing the layout in v, or NULL to use the default global section 7539 . A - The matrix 7540 . point - The point in the DM 7541 . values - The array of values 7542 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7543 7544 Fortran Notes: 7545 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7546 7547 Level: intermediate 7548 7549 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7550 @*/ 7551 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7552 { 7553 DM_Plex *mesh = (DM_Plex*) dm->data; 7554 PetscInt *indices; 7555 PetscInt numIndices; 7556 const PetscScalar *valuesOrig = values; 7557 PetscErrorCode ierr; 7558 7559 PetscFunctionBegin; 7560 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7561 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7562 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7563 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7564 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7565 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7566 7567 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7568 7569 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7570 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7571 if (ierr) { 7572 PetscMPIInt rank; 7573 PetscErrorCode ierr2; 7574 7575 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7576 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7577 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7578 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7579 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7580 SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7581 } 7582 if (mesh->printFEM > 1) { 7583 PetscInt i; 7584 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7585 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7586 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7587 } 7588 7589 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7590 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7591 PetscFunctionReturn(0); 7592 } 7593 7594 /*@C 7595 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7596 7597 Not collective 7598 7599 Input Parameters: 7600 + dmRow - The DM for the row fields 7601 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7602 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7603 . dmCol - The DM for the column fields 7604 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7605 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7606 . A - The matrix 7607 . point - The point in the DMs 7608 . values - The array of values 7609 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7610 7611 Level: intermediate 7612 7613 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7614 @*/ 7615 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7616 { 7617 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7618 PetscInt *indicesRow, *indicesCol; 7619 PetscInt numIndicesRow, numIndicesCol; 7620 const PetscScalar *valuesOrig = values; 7621 PetscErrorCode ierr; 7622 7623 PetscFunctionBegin; 7624 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7625 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7626 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7627 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7628 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7629 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7630 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7631 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7632 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7633 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7634 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7635 7636 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7637 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7638 7639 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7640 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7641 if (ierr) { 7642 PetscMPIInt rank; 7643 PetscErrorCode ierr2; 7644 7645 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7646 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7647 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7648 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7649 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7650 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7651 CHKERRQ(ierr); 7652 } 7653 7654 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7655 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7656 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7657 PetscFunctionReturn(0); 7658 } 7659 7660 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7661 { 7662 DM_Plex *mesh = (DM_Plex*) dmf->data; 7663 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7664 PetscInt *cpoints = NULL; 7665 PetscInt *findices, *cindices; 7666 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7667 PetscInt foffsets[32], coffsets[32]; 7668 DMPolytopeType ct; 7669 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7670 PetscErrorCode ierr; 7671 7672 PetscFunctionBegin; 7673 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7674 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7675 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7676 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7677 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7678 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7679 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7680 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7681 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7682 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7683 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7684 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7685 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7686 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7687 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7688 /* Column indices */ 7689 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7690 maxFPoints = numCPoints; 7691 /* Compress out points not in the section */ 7692 /* TODO: Squeeze out points with 0 dof as well */ 7693 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7694 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7695 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7696 cpoints[q*2] = cpoints[p]; 7697 cpoints[q*2+1] = cpoints[p+1]; 7698 ++q; 7699 } 7700 } 7701 numCPoints = q; 7702 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7703 PetscInt fdof; 7704 7705 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7706 if (!dof) continue; 7707 for (f = 0; f < numFields; ++f) { 7708 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7709 coffsets[f+1] += fdof; 7710 } 7711 numCIndices += dof; 7712 } 7713 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7714 /* Row indices */ 7715 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7716 { 7717 DMPlexTransform tr; 7718 DMPolytopeType *rct; 7719 PetscInt *rsize, *rcone, *rornt, Nt; 7720 7721 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7722 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7723 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7724 numSubcells = rsize[Nt-1]; 7725 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7726 } 7727 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7728 for (r = 0, q = 0; r < numSubcells; ++r) { 7729 /* TODO Map from coarse to fine cells */ 7730 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7731 /* Compress out points not in the section */ 7732 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7733 for (p = 0; p < numFPoints*2; p += 2) { 7734 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7735 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7736 if (!dof) continue; 7737 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7738 if (s < q) continue; 7739 ftotpoints[q*2] = fpoints[p]; 7740 ftotpoints[q*2+1] = fpoints[p+1]; 7741 ++q; 7742 } 7743 } 7744 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7745 } 7746 numFPoints = q; 7747 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7748 PetscInt fdof; 7749 7750 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7751 if (!dof) continue; 7752 for (f = 0; f < numFields; ++f) { 7753 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7754 foffsets[f+1] += fdof; 7755 } 7756 numFIndices += dof; 7757 } 7758 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7759 7760 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7761 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7762 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7763 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7764 if (numFields) { 7765 const PetscInt **permsF[32] = {NULL}; 7766 const PetscInt **permsC[32] = {NULL}; 7767 7768 for (f = 0; f < numFields; f++) { 7769 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7770 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7771 } 7772 for (p = 0; p < numFPoints; p++) { 7773 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7774 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7775 } 7776 for (p = 0; p < numCPoints; p++) { 7777 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7778 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7779 } 7780 for (f = 0; f < numFields; f++) { 7781 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7782 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7783 } 7784 } else { 7785 const PetscInt **permsF = NULL; 7786 const PetscInt **permsC = NULL; 7787 7788 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7789 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7790 for (p = 0, off = 0; p < numFPoints; p++) { 7791 const PetscInt *perm = permsF ? permsF[p] : NULL; 7792 7793 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7794 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7795 } 7796 for (p = 0, off = 0; p < numCPoints; p++) { 7797 const PetscInt *perm = permsC ? permsC[p] : NULL; 7798 7799 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7800 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7801 } 7802 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7803 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7804 } 7805 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7806 /* TODO: flips */ 7807 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7808 if (ierr) { 7809 PetscMPIInt rank; 7810 PetscErrorCode ierr2; 7811 7812 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7813 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7814 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7815 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7816 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7817 CHKERRQ(ierr); 7818 } 7819 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7820 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7821 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7822 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7823 PetscFunctionReturn(0); 7824 } 7825 7826 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7827 { 7828 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7829 PetscInt *cpoints = NULL; 7830 PetscInt foffsets[32], coffsets[32]; 7831 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7832 DMPolytopeType ct; 7833 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7834 PetscErrorCode ierr; 7835 7836 PetscFunctionBegin; 7837 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7838 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7839 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7840 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7841 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7842 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7843 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7844 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7845 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7846 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7847 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7848 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7849 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7850 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7851 /* Column indices */ 7852 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7853 maxFPoints = numCPoints; 7854 /* Compress out points not in the section */ 7855 /* TODO: Squeeze out points with 0 dof as well */ 7856 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7857 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7858 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7859 cpoints[q*2] = cpoints[p]; 7860 cpoints[q*2+1] = cpoints[p+1]; 7861 ++q; 7862 } 7863 } 7864 numCPoints = q; 7865 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7866 PetscInt fdof; 7867 7868 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7869 if (!dof) continue; 7870 for (f = 0; f < numFields; ++f) { 7871 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7872 coffsets[f+1] += fdof; 7873 } 7874 numCIndices += dof; 7875 } 7876 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7877 /* Row indices */ 7878 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7879 { 7880 DMPlexTransform tr; 7881 DMPolytopeType *rct; 7882 PetscInt *rsize, *rcone, *rornt, Nt; 7883 7884 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7885 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7886 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7887 numSubcells = rsize[Nt-1]; 7888 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7889 } 7890 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7891 for (r = 0, q = 0; r < numSubcells; ++r) { 7892 /* TODO Map from coarse to fine cells */ 7893 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7894 /* Compress out points not in the section */ 7895 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7896 for (p = 0; p < numFPoints*2; p += 2) { 7897 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7898 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7899 if (!dof) continue; 7900 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7901 if (s < q) continue; 7902 ftotpoints[q*2] = fpoints[p]; 7903 ftotpoints[q*2+1] = fpoints[p+1]; 7904 ++q; 7905 } 7906 } 7907 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7908 } 7909 numFPoints = q; 7910 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7911 PetscInt fdof; 7912 7913 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7914 if (!dof) continue; 7915 for (f = 0; f < numFields; ++f) { 7916 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7917 foffsets[f+1] += fdof; 7918 } 7919 numFIndices += dof; 7920 } 7921 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7922 7923 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7924 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7925 if (numFields) { 7926 const PetscInt **permsF[32] = {NULL}; 7927 const PetscInt **permsC[32] = {NULL}; 7928 7929 for (f = 0; f < numFields; f++) { 7930 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7931 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7932 } 7933 for (p = 0; p < numFPoints; p++) { 7934 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7935 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7936 } 7937 for (p = 0; p < numCPoints; p++) { 7938 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7939 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7940 } 7941 for (f = 0; f < numFields; f++) { 7942 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7943 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7944 } 7945 } else { 7946 const PetscInt **permsF = NULL; 7947 const PetscInt **permsC = NULL; 7948 7949 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7950 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7951 for (p = 0, off = 0; p < numFPoints; p++) { 7952 const PetscInt *perm = permsF ? permsF[p] : NULL; 7953 7954 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7955 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7956 } 7957 for (p = 0, off = 0; p < numCPoints; p++) { 7958 const PetscInt *perm = permsC ? permsC[p] : NULL; 7959 7960 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7961 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7962 } 7963 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7964 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7965 } 7966 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7967 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7968 PetscFunctionReturn(0); 7969 } 7970 7971 /*@C 7972 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7973 7974 Input Parameter: 7975 . dm - The DMPlex object 7976 7977 Output Parameter: 7978 . cellHeight - The height of a cell 7979 7980 Level: developer 7981 7982 .seealso DMPlexSetVTKCellHeight() 7983 @*/ 7984 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7985 { 7986 DM_Plex *mesh = (DM_Plex*) dm->data; 7987 7988 PetscFunctionBegin; 7989 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7990 PetscValidPointer(cellHeight, 2); 7991 *cellHeight = mesh->vtkCellHeight; 7992 PetscFunctionReturn(0); 7993 } 7994 7995 /*@C 7996 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7997 7998 Input Parameters: 7999 + dm - The DMPlex object 8000 - cellHeight - The height of a cell 8001 8002 Level: developer 8003 8004 .seealso DMPlexGetVTKCellHeight() 8005 @*/ 8006 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8007 { 8008 DM_Plex *mesh = (DM_Plex*) dm->data; 8009 8010 PetscFunctionBegin; 8011 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8012 mesh->vtkCellHeight = cellHeight; 8013 PetscFunctionReturn(0); 8014 } 8015 8016 /*@ 8017 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 8018 8019 Input Parameter: 8020 . dm - The DMPlex object 8021 8022 Output Parameters: 8023 + gcStart - The first ghost cell, or NULL 8024 - gcEnd - The upper bound on ghost cells, or NULL 8025 8026 Level: advanced 8027 8028 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 8029 @*/ 8030 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 8031 { 8032 DMLabel ctLabel; 8033 PetscErrorCode ierr; 8034 8035 PetscFunctionBegin; 8036 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8037 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 8038 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 8039 PetscFunctionReturn(0); 8040 } 8041 8042 /* We can easily have a form that takes an IS instead */ 8043 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8044 { 8045 PetscSection section, globalSection; 8046 PetscInt *numbers, p; 8047 PetscErrorCode ierr; 8048 8049 PetscFunctionBegin; 8050 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8051 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 8052 for (p = pStart; p < pEnd; ++p) { 8053 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 8054 } 8055 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 8056 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8057 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 8058 for (p = pStart; p < pEnd; ++p) { 8059 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 8060 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8061 else numbers[p-pStart] += shift; 8062 } 8063 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 8064 if (globalSize) { 8065 PetscLayout layout; 8066 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 8067 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 8068 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 8069 } 8070 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8071 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8072 PetscFunctionReturn(0); 8073 } 8074 8075 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8076 { 8077 PetscInt cellHeight, cStart, cEnd; 8078 PetscErrorCode ierr; 8079 8080 PetscFunctionBegin; 8081 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8082 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8083 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8084 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 8085 PetscFunctionReturn(0); 8086 } 8087 8088 /*@ 8089 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 8090 8091 Input Parameter: 8092 . dm - The DMPlex object 8093 8094 Output Parameter: 8095 . globalCellNumbers - Global cell numbers for all cells on this process 8096 8097 Level: developer 8098 8099 .seealso DMPlexGetVertexNumbering() 8100 @*/ 8101 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8102 { 8103 DM_Plex *mesh = (DM_Plex*) dm->data; 8104 PetscErrorCode ierr; 8105 8106 PetscFunctionBegin; 8107 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8108 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 8109 *globalCellNumbers = mesh->globalCellNumbers; 8110 PetscFunctionReturn(0); 8111 } 8112 8113 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8114 { 8115 PetscInt vStart, vEnd; 8116 PetscErrorCode ierr; 8117 8118 PetscFunctionBegin; 8119 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8120 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8121 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 8122 PetscFunctionReturn(0); 8123 } 8124 8125 /*@ 8126 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 8127 8128 Input Parameter: 8129 . dm - The DMPlex object 8130 8131 Output Parameter: 8132 . globalVertexNumbers - Global vertex numbers for all vertices on this process 8133 8134 Level: developer 8135 8136 .seealso DMPlexGetCellNumbering() 8137 @*/ 8138 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8139 { 8140 DM_Plex *mesh = (DM_Plex*) dm->data; 8141 PetscErrorCode ierr; 8142 8143 PetscFunctionBegin; 8144 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8145 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 8146 *globalVertexNumbers = mesh->globalVertexNumbers; 8147 PetscFunctionReturn(0); 8148 } 8149 8150 /*@ 8151 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 8152 8153 Input Parameter: 8154 . dm - The DMPlex object 8155 8156 Output Parameter: 8157 . globalPointNumbers - Global numbers for all points on this process 8158 8159 Level: developer 8160 8161 .seealso DMPlexGetCellNumbering() 8162 @*/ 8163 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8164 { 8165 IS nums[4]; 8166 PetscInt depths[4], gdepths[4], starts[4]; 8167 PetscInt depth, d, shift = 0; 8168 PetscErrorCode ierr; 8169 8170 PetscFunctionBegin; 8171 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8172 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8173 /* For unstratified meshes use dim instead of depth */ 8174 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 8175 for (d = 0; d <= depth; ++d) { 8176 PetscInt end; 8177 8178 depths[d] = depth-d; 8179 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 8180 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8181 } 8182 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 8183 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8184 for (d = 0; d <= depth; ++d) { 8185 PetscCheckFalse(starts[d] >= 0 && depths[d] != gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8186 } 8187 for (d = 0; d <= depth; ++d) { 8188 PetscInt pStart, pEnd, gsize; 8189 8190 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 8191 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 8192 shift += gsize; 8193 } 8194 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 8195 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 8196 PetscFunctionReturn(0); 8197 } 8198 8199 /*@ 8200 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 8201 8202 Input Parameter: 8203 . dm - The DMPlex object 8204 8205 Output Parameter: 8206 . ranks - The rank field 8207 8208 Options Database Keys: 8209 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 8210 8211 Level: intermediate 8212 8213 .seealso: DMView() 8214 @*/ 8215 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8216 { 8217 DM rdm; 8218 PetscFE fe; 8219 PetscScalar *r; 8220 PetscMPIInt rank; 8221 DMPolytopeType ct; 8222 PetscInt dim, cStart, cEnd, c; 8223 PetscBool simplex; 8224 PetscErrorCode ierr; 8225 8226 PetscFunctionBeginUser; 8227 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8228 PetscValidPointer(ranks, 2); 8229 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 8230 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8231 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8232 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8233 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 8234 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 8235 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 8236 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 8237 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8238 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8239 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8240 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 8241 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 8242 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 8243 for (c = cStart; c < cEnd; ++c) { 8244 PetscScalar *lr; 8245 8246 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 8247 if (lr) *lr = rank; 8248 } 8249 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8250 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8251 PetscFunctionReturn(0); 8252 } 8253 8254 /*@ 8255 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8256 8257 Input Parameters: 8258 + dm - The DMPlex 8259 - label - The DMLabel 8260 8261 Output Parameter: 8262 . val - The label value field 8263 8264 Options Database Keys: 8265 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8266 8267 Level: intermediate 8268 8269 .seealso: DMView() 8270 @*/ 8271 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8272 { 8273 DM rdm; 8274 PetscFE fe; 8275 PetscScalar *v; 8276 PetscInt dim, cStart, cEnd, c; 8277 PetscErrorCode ierr; 8278 8279 PetscFunctionBeginUser; 8280 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8281 PetscValidPointer(label, 2); 8282 PetscValidPointer(val, 3); 8283 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8284 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8285 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8286 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8287 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8288 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8289 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8290 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8291 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8292 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8293 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8294 for (c = cStart; c < cEnd; ++c) { 8295 PetscScalar *lv; 8296 PetscInt cval; 8297 8298 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8299 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8300 *lv = cval; 8301 } 8302 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8303 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8304 PetscFunctionReturn(0); 8305 } 8306 8307 /*@ 8308 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8309 8310 Input Parameter: 8311 . dm - The DMPlex object 8312 8313 Notes: 8314 This is a useful diagnostic when creating meshes programmatically. 8315 8316 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8317 8318 Level: developer 8319 8320 .seealso: DMCreate(), DMSetFromOptions() 8321 @*/ 8322 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8323 { 8324 PetscSection coneSection, supportSection; 8325 const PetscInt *cone, *support; 8326 PetscInt coneSize, c, supportSize, s; 8327 PetscInt pStart, pEnd, p, pp, csize, ssize; 8328 PetscBool storagecheck = PETSC_TRUE; 8329 PetscErrorCode ierr; 8330 8331 PetscFunctionBegin; 8332 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8333 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8334 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8335 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8336 /* Check that point p is found in the support of its cone points, and vice versa */ 8337 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8338 for (p = pStart; p < pEnd; ++p) { 8339 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8340 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8341 for (c = 0; c < coneSize; ++c) { 8342 PetscBool dup = PETSC_FALSE; 8343 PetscInt d; 8344 for (d = c-1; d >= 0; --d) { 8345 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8346 } 8347 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8348 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8349 for (s = 0; s < supportSize; ++s) { 8350 if (support[s] == p) break; 8351 } 8352 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8353 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8354 for (s = 0; s < coneSize; ++s) { 8355 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8356 } 8357 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8358 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8359 for (s = 0; s < supportSize; ++s) { 8360 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8361 } 8362 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8363 PetscCheckFalse(dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8364 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8365 } 8366 } 8367 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8368 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8369 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8370 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8371 for (s = 0; s < supportSize; ++s) { 8372 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8373 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8374 for (c = 0; c < coneSize; ++c) { 8375 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8376 if (cone[c] != pp) { c = 0; break; } 8377 if (cone[c] == p) break; 8378 } 8379 if (c >= coneSize) { 8380 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8381 for (c = 0; c < supportSize; ++c) { 8382 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8383 } 8384 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8385 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8386 for (c = 0; c < coneSize; ++c) { 8387 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8388 } 8389 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8390 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8391 } 8392 } 8393 } 8394 if (storagecheck) { 8395 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8396 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8397 PetscCheckFalse(csize != ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8398 } 8399 PetscFunctionReturn(0); 8400 } 8401 8402 /* 8403 For submeshes with cohesive cells (see DMPlexConstructCohesiveCells()), we allow a special case where some of the boundary of a face (edges and vertices) are not duplicated. We call these special boundary points "unsplit", since the same edge or vertex appears in both copies of the face. These unsplit points throw off our counting, so we have to explicitly account for them here. 8404 */ 8405 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8406 { 8407 DMPolytopeType cct; 8408 PetscInt ptpoints[4]; 8409 const PetscInt *cone, *ccone, *ptcone; 8410 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8411 PetscErrorCode ierr; 8412 8413 PetscFunctionBegin; 8414 *unsplit = 0; 8415 switch (ct) { 8416 case DM_POLYTOPE_POINT_PRISM_TENSOR: 8417 ptpoints[npt++] = c; 8418 break; 8419 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8420 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8421 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8422 for (cp = 0; cp < coneSize; ++cp) { 8423 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8424 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8425 } 8426 break; 8427 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8428 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8429 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8430 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8431 for (cp = 0; cp < coneSize; ++cp) { 8432 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8433 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8434 for (ccp = 0; ccp < cconeSize; ++ccp) { 8435 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8436 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8437 PetscInt p; 8438 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8439 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8440 } 8441 } 8442 } 8443 break; 8444 default: break; 8445 } 8446 for (pt = 0; pt < npt; ++pt) { 8447 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8448 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8449 } 8450 PetscFunctionReturn(0); 8451 } 8452 8453 /*@ 8454 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8455 8456 Input Parameters: 8457 + dm - The DMPlex object 8458 - cellHeight - Normally 0 8459 8460 Notes: 8461 This is a useful diagnostic when creating meshes programmatically. 8462 Currently applicable only to homogeneous simplex or tensor meshes. 8463 8464 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8465 8466 Level: developer 8467 8468 .seealso: DMCreate(), DMSetFromOptions() 8469 @*/ 8470 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8471 { 8472 DMPlexInterpolatedFlag interp; 8473 DMPolytopeType ct; 8474 PetscInt vStart, vEnd, cStart, cEnd, c; 8475 PetscErrorCode ierr; 8476 8477 PetscFunctionBegin; 8478 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8479 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8480 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8481 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8482 for (c = cStart; c < cEnd; ++c) { 8483 PetscInt *closure = NULL; 8484 PetscInt coneSize, closureSize, cl, Nv = 0; 8485 8486 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8487 PetscCheckFalse((PetscInt) ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8488 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8489 if (interp == DMPLEX_INTERPOLATED_FULL) { 8490 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8491 PetscCheckFalse(coneSize != DMPolytopeTypeGetConeSize(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has cone size %D != %D", c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct)); 8492 } 8493 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8494 for (cl = 0; cl < closureSize*2; cl += 2) { 8495 const PetscInt p = closure[cl]; 8496 if ((p >= vStart) && (p < vEnd)) ++Nv; 8497 } 8498 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8499 /* Special Case: Tensor faces with identified vertices */ 8500 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8501 PetscInt unsplit; 8502 8503 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8504 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8505 } 8506 PetscCheckFalse(Nv != DMPolytopeTypeGetNumVertices(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D vertices != %D", c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct)); 8507 } 8508 PetscFunctionReturn(0); 8509 } 8510 8511 /*@ 8512 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8513 8514 Not Collective 8515 8516 Input Parameters: 8517 + dm - The DMPlex object 8518 - cellHeight - Normally 0 8519 8520 Notes: 8521 This is a useful diagnostic when creating meshes programmatically. 8522 This routine is only relevant for meshes that are fully interpolated across all ranks. 8523 It will error out if a partially interpolated mesh is given on some rank. 8524 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8525 8526 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8527 8528 Level: developer 8529 8530 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8531 @*/ 8532 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8533 { 8534 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8535 PetscErrorCode ierr; 8536 DMPlexInterpolatedFlag interpEnum; 8537 8538 PetscFunctionBegin; 8539 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8540 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8541 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8542 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8543 PetscMPIInt rank; 8544 MPI_Comm comm; 8545 8546 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8547 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8548 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8549 } 8550 8551 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8552 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8553 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8554 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8555 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8556 for (c = cStart; c < cEnd; ++c) { 8557 const PetscInt *cone, *ornt, *faceSizes, *faces; 8558 const DMPolytopeType *faceTypes; 8559 DMPolytopeType ct; 8560 PetscInt numFaces, coneSize, f; 8561 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8562 8563 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8564 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8565 if (unsplit) continue; 8566 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8567 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8568 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8569 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8570 for (cl = 0; cl < closureSize*2; cl += 2) { 8571 const PetscInt p = closure[cl]; 8572 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8573 } 8574 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8575 PetscCheckFalse(coneSize != numFaces,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D faces but should have %D", c, DMPolytopeTypes[ct], coneSize, numFaces); 8576 for (f = 0; f < numFaces; ++f) { 8577 DMPolytopeType fct; 8578 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8579 8580 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8581 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8582 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8583 const PetscInt p = fclosure[cl]; 8584 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8585 } 8586 PetscCheckFalse(fnumCorners != faceSizes[f],PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %D) of cell %D of type %s has %D vertices but should have %D", cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], fnumCorners, faceSizes[f]); 8587 for (v = 0; v < fnumCorners; ++v) { 8588 if (fclosure[v] != faces[fOff+v]) { 8589 PetscInt v1; 8590 8591 ierr = PetscPrintf(PETSC_COMM_SELF, "face closure:");CHKERRQ(ierr); 8592 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]);CHKERRQ(ierr);} 8593 ierr = PetscPrintf(PETSC_COMM_SELF, "\ncell face:");CHKERRQ(ierr); 8594 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]);CHKERRQ(ierr);} 8595 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8596 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %d, ornt %D) of cell %D of type %s vertex %D, %D != %D", cone[f], DMPolytopeTypes[fct], f, ornt[f], c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff+v]); 8597 } 8598 } 8599 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8600 fOff += faceSizes[f]; 8601 } 8602 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8603 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8604 } 8605 } 8606 PetscFunctionReturn(0); 8607 } 8608 8609 /*@ 8610 DMPlexCheckGeometry - Check the geometry of mesh cells 8611 8612 Input Parameter: 8613 . dm - The DMPlex object 8614 8615 Notes: 8616 This is a useful diagnostic when creating meshes programmatically. 8617 8618 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8619 8620 Level: developer 8621 8622 .seealso: DMCreate(), DMSetFromOptions() 8623 @*/ 8624 PetscErrorCode DMPlexCheckGeometry(DM dm) 8625 { 8626 Vec coordinates; 8627 PetscReal detJ, J[9], refVol = 1.0; 8628 PetscReal vol; 8629 PetscBool periodic; 8630 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8631 PetscErrorCode ierr; 8632 8633 PetscFunctionBegin; 8634 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8635 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8636 if (dim != dE) PetscFunctionReturn(0); 8637 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8638 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8639 for (d = 0; d < dim; ++d) refVol *= 2.0; 8640 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8641 /* Make sure local coordinates are created, because that step is collective */ 8642 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8643 for (c = cStart; c < cEnd; ++c) { 8644 DMPolytopeType ct; 8645 PetscInt unsplit; 8646 PetscBool ignoreZeroVol = PETSC_FALSE; 8647 8648 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8649 switch (ct) { 8650 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8651 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8652 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8653 ignoreZeroVol = PETSC_TRUE; break; 8654 default: break; 8655 } 8656 switch (ct) { 8657 case DM_POLYTOPE_TRI_PRISM: 8658 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8659 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8660 case DM_POLYTOPE_PYRAMID: 8661 continue; 8662 default: break; 8663 } 8664 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8665 if (unsplit) continue; 8666 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8667 PetscCheckFalse(detJ < -PETSC_SMALL || (detJ <= 0.0 && !ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double) detJ); 8668 ierr = PetscInfo(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8669 if (depth > 1 && !periodic) { 8670 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8671 PetscCheckFalse(vol < -PETSC_SMALL || (vol <= 0.0 && !ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double) vol); 8672 ierr = PetscInfo(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8673 } 8674 } 8675 PetscFunctionReturn(0); 8676 } 8677 8678 /*@ 8679 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8680 8681 Input Parameters: 8682 . dm - The DMPlex object 8683 8684 Notes: 8685 This is mainly intended for debugging/testing purposes. 8686 It currently checks only meshes with no partition overlapping. 8687 8688 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8689 8690 Level: developer 8691 8692 .seealso: DMGetPointSF(), DMSetFromOptions() 8693 @*/ 8694 PetscErrorCode DMPlexCheckPointSF(DM dm) 8695 { 8696 PetscSF pointSF; 8697 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8698 const PetscInt *locals, *rootdegree; 8699 PetscBool distributed; 8700 PetscErrorCode ierr; 8701 8702 PetscFunctionBegin; 8703 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8704 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8705 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8706 if (!distributed) PetscFunctionReturn(0); 8707 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8708 if (overlap) { 8709 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8710 PetscFunctionReturn(0); 8711 } 8712 PetscCheckFalse(!pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8713 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8714 PetscCheckFalse(nroots < 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8715 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8716 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8717 8718 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8719 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8720 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8721 for (l = 0; l < nleaves; ++l) { 8722 const PetscInt point = locals[l]; 8723 8724 PetscCheckFalse(point >= cStart && point < cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8725 } 8726 8727 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8728 for (l = 0; l < nleaves; ++l) { 8729 const PetscInt point = locals[l]; 8730 const PetscInt *cone; 8731 PetscInt coneSize, c, idx; 8732 8733 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8734 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8735 for (c = 0; c < coneSize; ++c) { 8736 if (!rootdegree[cone[c]]) { 8737 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8738 PetscCheckFalse(idx < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8739 } 8740 } 8741 } 8742 PetscFunctionReturn(0); 8743 } 8744 8745 PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8746 { 8747 PetscErrorCode ierr; 8748 8749 PetscFunctionBegin; 8750 ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr); 8751 ierr = DMPlexCheckSkeleton(dm, cellHeight);CHKERRQ(ierr); 8752 ierr = DMPlexCheckFaces(dm, cellHeight);CHKERRQ(ierr); 8753 ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr); 8754 ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 8755 ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr); 8756 PetscFunctionReturn(0); 8757 } 8758 8759 typedef struct cell_stats 8760 { 8761 PetscReal min, max, sum, squaresum; 8762 PetscInt count; 8763 } cell_stats_t; 8764 8765 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8766 { 8767 PetscInt i, N = *len; 8768 8769 for (i = 0; i < N; i++) { 8770 cell_stats_t *A = (cell_stats_t *) a; 8771 cell_stats_t *B = (cell_stats_t *) b; 8772 8773 B->min = PetscMin(A->min,B->min); 8774 B->max = PetscMax(A->max,B->max); 8775 B->sum += A->sum; 8776 B->squaresum += A->squaresum; 8777 B->count += A->count; 8778 } 8779 } 8780 8781 /*@ 8782 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8783 8784 Collective on dm 8785 8786 Input Parameters: 8787 + dm - The DMPlex object 8788 . output - If true, statistics will be displayed on stdout 8789 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8790 8791 Notes: 8792 This is mainly intended for debugging/testing purposes. 8793 8794 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8795 8796 Level: developer 8797 8798 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8799 @*/ 8800 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8801 { 8802 DM dmCoarse; 8803 cell_stats_t stats, globalStats; 8804 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8805 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8806 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8807 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8808 PetscMPIInt rank,size; 8809 PetscErrorCode ierr; 8810 8811 PetscFunctionBegin; 8812 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8813 stats.min = PETSC_MAX_REAL; 8814 stats.max = PETSC_MIN_REAL; 8815 stats.sum = stats.squaresum = 0.; 8816 stats.count = 0; 8817 8818 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8819 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8820 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8821 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8822 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8823 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8824 for (c = cStart; c < cEnd; c++) { 8825 PetscInt i; 8826 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8827 8828 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8829 PetscCheckFalse(detJ < 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8830 for (i = 0; i < PetscSqr(cdim); ++i) { 8831 frobJ += J[i] * J[i]; 8832 frobInvJ += invJ[i] * invJ[i]; 8833 } 8834 cond2 = frobJ * frobInvJ; 8835 cond = PetscSqrtReal(cond2); 8836 8837 stats.min = PetscMin(stats.min,cond); 8838 stats.max = PetscMax(stats.max,cond); 8839 stats.sum += cond; 8840 stats.squaresum += cond2; 8841 stats.count++; 8842 if (output && cond > limit) { 8843 PetscSection coordSection; 8844 Vec coordsLocal; 8845 PetscScalar *coords = NULL; 8846 PetscInt Nv, d, clSize, cl, *closure = NULL; 8847 8848 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8849 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8850 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8851 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8852 for (i = 0; i < Nv/cdim; ++i) { 8853 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8854 for (d = 0; d < cdim; ++d) { 8855 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8856 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8857 } 8858 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8859 } 8860 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8861 for (cl = 0; cl < clSize*2; cl += 2) { 8862 const PetscInt edge = closure[cl]; 8863 8864 if ((edge >= eStart) && (edge < eEnd)) { 8865 PetscReal len; 8866 8867 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8868 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8869 } 8870 } 8871 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8872 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8873 } 8874 } 8875 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8876 8877 if (size > 1) { 8878 PetscMPIInt blockLengths[2] = {4,1}; 8879 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8880 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8881 MPI_Op statReduce; 8882 8883 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8884 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8885 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8886 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8887 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8888 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8889 } else { 8890 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8891 } 8892 if (rank == 0) { 8893 count = globalStats.count; 8894 min = globalStats.min; 8895 max = globalStats.max; 8896 mean = globalStats.sum / globalStats.count; 8897 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8898 } 8899 8900 if (output) { 8901 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); 8902 } 8903 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8904 8905 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8906 if (dmCoarse) { 8907 PetscBool isplex; 8908 8909 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8910 if (isplex) { 8911 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8912 } 8913 } 8914 PetscFunctionReturn(0); 8915 } 8916 8917 /*@ 8918 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8919 orthogonal quality below given tolerance. 8920 8921 Collective on dm 8922 8923 Input Parameters: 8924 + dm - The DMPlex object 8925 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8926 - atol - [0, 1] Absolute tolerance for tagging cells. 8927 8928 Output Parameters: 8929 + OrthQual - Vec containing orthogonal quality per cell 8930 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8931 8932 Options Database Keys: 8933 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8934 supported. 8935 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8936 8937 Notes: 8938 Orthogonal quality is given by the following formula: 8939 8940 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8941 8942 Where A_i is the i'th face-normal vector, f_i is the vector from the cell centroid to the i'th face centroid, and c_i 8943 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8944 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8945 calculating the cosine of the angle between these vectors. 8946 8947 Orthogonal quality ranges from 1 (best) to 0 (worst). 8948 8949 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8950 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8951 8952 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8953 8954 Level: intermediate 8955 8956 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8957 @*/ 8958 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8959 { 8960 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8961 PetscInt *idx; 8962 PetscScalar *oqVals; 8963 const PetscScalar *cellGeomArr, *faceGeomArr; 8964 PetscReal *ci, *fi, *Ai; 8965 MPI_Comm comm; 8966 Vec cellgeom, facegeom; 8967 DM dmFace, dmCell; 8968 IS glob; 8969 ISLocalToGlobalMapping ltog; 8970 PetscViewer vwr; 8971 PetscErrorCode ierr; 8972 8973 PetscFunctionBegin; 8974 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8975 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8976 PetscValidPointer(OrthQual, 4); 8977 PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 8978 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8979 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8980 PetscCheckFalse(nc < 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8981 { 8982 DMPlexInterpolatedFlag interpFlag; 8983 8984 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8985 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8986 PetscMPIInt rank; 8987 8988 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8989 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8990 } 8991 } 8992 if (OrthQualLabel) { 8993 PetscValidPointer(OrthQualLabel, 5); 8994 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8995 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8996 } else {*OrthQualLabel = NULL;} 8997 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8998 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8999 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 9000 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 9001 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 9002 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 9003 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 9004 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 9005 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 9006 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 9007 ierr = ISDestroy(&glob);CHKERRQ(ierr); 9008 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 9009 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 9010 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 9011 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 9012 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 9013 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 9014 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 9015 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 9016 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9017 PetscInt cellarr[2], *adj = NULL; 9018 PetscScalar *cArr, *fArr; 9019 PetscReal minvalc = 1.0, minvalf = 1.0; 9020 PetscFVCellGeom *cg; 9021 9022 idx[cellIter] = cell-cStart; 9023 cellarr[0] = cell; 9024 /* Make indexing into cellGeom easier */ 9025 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 9026 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 9027 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 9028 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 9029 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 9030 PetscInt i; 9031 const PetscInt neigh = adj[cellneigh]; 9032 PetscReal normci = 0, normfi = 0, normai = 0; 9033 PetscFVCellGeom *cgneigh; 9034 PetscFVFaceGeom *fg; 9035 9036 /* Don't count ourselves in the neighbor list */ 9037 if (neigh == cell) continue; 9038 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 9039 cellarr[1] = neigh; 9040 { 9041 PetscInt numcovpts; 9042 const PetscInt *covpts; 9043 9044 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9045 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 9046 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9047 } 9048 9049 /* Compute c_i, f_i and their norms */ 9050 for (i = 0; i < nc; i++) { 9051 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9052 fi[i] = fg->centroid[i] - cg->centroid[i]; 9053 Ai[i] = fg->normal[i]; 9054 normci += PetscPowReal(ci[i], 2); 9055 normfi += PetscPowReal(fi[i], 2); 9056 normai += PetscPowReal(Ai[i], 2); 9057 } 9058 normci = PetscSqrtReal(normci); 9059 normfi = PetscSqrtReal(normfi); 9060 normai = PetscSqrtReal(normai); 9061 9062 /* Normalize and compute for each face-cell-normal pair */ 9063 for (i = 0; i < nc; i++) { 9064 ci[i] = ci[i]/normci; 9065 fi[i] = fi[i]/normfi; 9066 Ai[i] = Ai[i]/normai; 9067 /* PetscAbs because I don't know if normals are guaranteed to point out */ 9068 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9069 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9070 } 9071 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9072 minvalc = PetscRealPart(cArr[cellneighiter]); 9073 } 9074 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9075 minvalf = PetscRealPart(fArr[cellneighiter]); 9076 } 9077 } 9078 ierr = PetscFree(adj);CHKERRQ(ierr); 9079 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 9080 /* Defer to cell if they're equal */ 9081 oqVals[cellIter] = PetscMin(minvalf, minvalc); 9082 if (OrthQualLabel) { 9083 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 9084 } 9085 } 9086 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 9087 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 9088 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 9089 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 9090 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 9091 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 9092 if (OrthQualLabel) { 9093 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 9094 } 9095 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 9096 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 9097 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 9098 PetscFunctionReturn(0); 9099 } 9100 9101 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 9102 * interpolator construction */ 9103 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9104 { 9105 PetscSection section, newSection, gsection; 9106 PetscSF sf; 9107 PetscBool hasConstraints, ghasConstraints; 9108 PetscErrorCode ierr; 9109 9110 PetscFunctionBegin; 9111 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9112 PetscValidPointer(odm,2); 9113 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9114 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 9115 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 9116 if (!ghasConstraints) { 9117 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 9118 *odm = dm; 9119 PetscFunctionReturn(0); 9120 } 9121 ierr = DMClone(dm, odm);CHKERRQ(ierr); 9122 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 9123 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 9124 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 9125 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 9126 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 9127 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 9128 PetscFunctionReturn(0); 9129 } 9130 9131 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9132 { 9133 DM dmco, dmfo; 9134 Mat interpo; 9135 Vec rscale; 9136 Vec cglobalo, clocal; 9137 Vec fglobal, fglobalo, flocal; 9138 PetscBool regular; 9139 PetscErrorCode ierr; 9140 9141 PetscFunctionBegin; 9142 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 9143 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 9144 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 9145 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 9146 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 9147 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 9148 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 9149 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 9150 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 9151 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 9152 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 9153 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 9154 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 9155 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 9156 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 9157 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 9158 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 9159 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9160 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9161 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 9162 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9163 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9164 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9165 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9166 *shift = fglobal; 9167 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 9168 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 9169 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 9170 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 9171 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9172 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 9173 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 9174 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 9175 PetscFunctionReturn(0); 9176 } 9177 9178 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9179 { 9180 PetscObject shifto; 9181 Vec shift; 9182 9183 PetscErrorCode ierr; 9184 9185 PetscFunctionBegin; 9186 if (!interp) { 9187 Vec rscale; 9188 9189 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 9190 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9191 } else { 9192 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 9193 } 9194 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 9195 if (!shifto) { 9196 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 9197 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 9198 shifto = (PetscObject) shift; 9199 ierr = VecDestroy(&shift);CHKERRQ(ierr); 9200 } 9201 shift = (Vec) shifto; 9202 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 9203 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 9204 ierr = MatDestroy(&interp);CHKERRQ(ierr); 9205 PetscFunctionReturn(0); 9206 } 9207 9208 /* Pointwise interpolation 9209 Just code FEM for now 9210 u^f = I u^c 9211 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 9212 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 9213 I_{ij} = psi^f_i phi^c_j 9214 */ 9215 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9216 { 9217 PetscSection gsc, gsf; 9218 PetscInt m, n; 9219 void *ctx; 9220 DM cdm; 9221 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9222 PetscErrorCode ierr; 9223 9224 PetscFunctionBegin; 9225 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9226 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9227 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9228 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9229 9230 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 9231 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 9232 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9233 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 9234 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9235 9236 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9237 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9238 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 9239 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 9240 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 9241 if (scaling) { 9242 /* Use naive scaling */ 9243 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 9244 } 9245 PetscFunctionReturn(0); 9246 } 9247 9248 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9249 { 9250 PetscErrorCode ierr; 9251 VecScatter ctx; 9252 9253 PetscFunctionBegin; 9254 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 9255 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 9256 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 9257 PetscFunctionReturn(0); 9258 } 9259 9260 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9261 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9262 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9263 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9264 { 9265 const PetscInt Nc = uOff[1] - uOff[0]; 9266 PetscInt c; 9267 for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 9268 } 9269 9270 PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9271 { 9272 DM dmc; 9273 PetscDS ds; 9274 Vec ones, locmass; 9275 IS cellIS; 9276 PetscFormKey key; 9277 PetscInt depth; 9278 PetscErrorCode ierr; 9279 9280 PetscFunctionBegin; 9281 ierr = DMClone(dm, &dmc);CHKERRQ(ierr); 9282 ierr = DMCopyDisc(dm, dmc);CHKERRQ(ierr); 9283 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9284 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9285 ierr = DMCreateGlobalVector(dmc, mass);CHKERRQ(ierr); 9286 ierr = DMGetLocalVector(dmc, &ones);CHKERRQ(ierr); 9287 ierr = DMGetLocalVector(dmc, &locmass);CHKERRQ(ierr); 9288 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9289 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9290 ierr = VecSet(locmass, 0.0);CHKERRQ(ierr); 9291 ierr = VecSet(ones, 1.0);CHKERRQ(ierr); 9292 key.label = NULL; 9293 key.value = 0; 9294 key.field = 0; 9295 key.part = 0; 9296 ierr = DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL);CHKERRQ(ierr); 9297 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9298 ierr = VecSet(*mass, 0.0);CHKERRQ(ierr); 9299 ierr = DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9300 ierr = DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9301 ierr = DMRestoreLocalVector(dmc, &ones);CHKERRQ(ierr); 9302 ierr = DMRestoreLocalVector(dmc, &locmass);CHKERRQ(ierr); 9303 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9304 PetscFunctionReturn(0); 9305 } 9306 9307 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9308 { 9309 PetscSection gsc, gsf; 9310 PetscInt m, n; 9311 void *ctx; 9312 DM cdm; 9313 PetscBool regular; 9314 PetscErrorCode ierr; 9315 9316 PetscFunctionBegin; 9317 if (dmFine == dmCoarse) { 9318 DM dmc; 9319 PetscDS ds; 9320 PetscWeakForm wf; 9321 Vec u; 9322 IS cellIS; 9323 PetscFormKey key; 9324 PetscInt depth; 9325 9326 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9327 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9328 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9329 ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 9330 ierr = PetscWeakFormClear(wf);CHKERRQ(ierr); 9331 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9332 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9333 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9334 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9335 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9336 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9337 key.label = NULL; 9338 key.value = 0; 9339 key.field = 0; 9340 key.part = 0; 9341 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9342 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9343 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9344 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9345 } else { 9346 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9347 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9348 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9349 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9350 9351 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9352 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9353 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9354 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9355 9356 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9357 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9358 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9359 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9360 } 9361 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9362 PetscFunctionReturn(0); 9363 } 9364 9365 /*@ 9366 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9367 9368 Input Parameter: 9369 . dm - The DMPlex object 9370 9371 Output Parameter: 9372 . regular - The flag 9373 9374 Level: intermediate 9375 9376 .seealso: DMPlexSetRegularRefinement() 9377 @*/ 9378 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9379 { 9380 PetscFunctionBegin; 9381 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9382 PetscValidPointer(regular, 2); 9383 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9384 PetscFunctionReturn(0); 9385 } 9386 9387 /*@ 9388 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9389 9390 Input Parameters: 9391 + dm - The DMPlex object 9392 - regular - The flag 9393 9394 Level: intermediate 9395 9396 .seealso: DMPlexGetRegularRefinement() 9397 @*/ 9398 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9399 { 9400 PetscFunctionBegin; 9401 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9402 ((DM_Plex *) dm->data)->regularRefinement = regular; 9403 PetscFunctionReturn(0); 9404 } 9405 9406 /* anchors */ 9407 /*@ 9408 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9409 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9410 9411 not collective 9412 9413 Input Parameter: 9414 . dm - The DMPlex object 9415 9416 Output Parameters: 9417 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9418 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9419 9420 Level: intermediate 9421 9422 .seealso: DMPlexSetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9423 @*/ 9424 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9425 { 9426 DM_Plex *plex = (DM_Plex *)dm->data; 9427 PetscErrorCode ierr; 9428 9429 PetscFunctionBegin; 9430 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9431 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9432 if (anchorSection) *anchorSection = plex->anchorSection; 9433 if (anchorIS) *anchorIS = plex->anchorIS; 9434 PetscFunctionReturn(0); 9435 } 9436 9437 /*@ 9438 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9439 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9440 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9441 9442 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9443 DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9444 9445 collective on dm 9446 9447 Input Parameters: 9448 + dm - The DMPlex object 9449 . 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). 9450 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9451 9452 The reference counts of anchorSection and anchorIS are incremented. 9453 9454 Level: intermediate 9455 9456 .seealso: DMPlexGetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9457 @*/ 9458 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9459 { 9460 DM_Plex *plex = (DM_Plex *)dm->data; 9461 PetscMPIInt result; 9462 PetscErrorCode ierr; 9463 9464 PetscFunctionBegin; 9465 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9466 if (anchorSection) { 9467 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9468 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9469 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9470 } 9471 if (anchorIS) { 9472 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9473 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9474 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9475 } 9476 9477 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9478 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9479 plex->anchorSection = anchorSection; 9480 9481 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9482 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9483 plex->anchorIS = anchorIS; 9484 9485 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9486 PetscInt size, a, pStart, pEnd; 9487 const PetscInt *anchors; 9488 9489 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9490 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9491 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9492 for (a = 0; a < size; a++) { 9493 PetscInt p; 9494 9495 p = anchors[a]; 9496 if (p >= pStart && p < pEnd) { 9497 PetscInt dof; 9498 9499 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9500 if (dof) { 9501 PetscErrorCode ierr2; 9502 9503 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9504 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9505 } 9506 } 9507 } 9508 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9509 } 9510 /* reset the generic constraints */ 9511 ierr = DMSetDefaultConstraints(dm,NULL,NULL,NULL);CHKERRQ(ierr); 9512 PetscFunctionReturn(0); 9513 } 9514 9515 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9516 { 9517 PetscSection anchorSection; 9518 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9519 PetscErrorCode ierr; 9520 9521 PetscFunctionBegin; 9522 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9523 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9524 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9525 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9526 if (numFields) { 9527 PetscInt f; 9528 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9529 9530 for (f = 0; f < numFields; f++) { 9531 PetscInt numComp; 9532 9533 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9534 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9535 } 9536 } 9537 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9538 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9539 pStart = PetscMax(pStart,sStart); 9540 pEnd = PetscMin(pEnd,sEnd); 9541 pEnd = PetscMax(pStart,pEnd); 9542 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9543 for (p = pStart; p < pEnd; p++) { 9544 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9545 if (dof) { 9546 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9547 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9548 for (f = 0; f < numFields; f++) { 9549 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9550 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9551 } 9552 } 9553 } 9554 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9555 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9556 PetscFunctionReturn(0); 9557 } 9558 9559 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9560 { 9561 PetscSection aSec; 9562 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9563 const PetscInt *anchors; 9564 PetscInt numFields, f; 9565 IS aIS; 9566 PetscErrorCode ierr; 9567 MatType mtype; 9568 PetscBool iscuda,iskokkos; 9569 9570 PetscFunctionBegin; 9571 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9572 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9573 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9574 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9575 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9576 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9577 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9578 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9579 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9580 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9581 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9582 else mtype = MATSEQAIJ; 9583 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9584 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9585 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9586 /* cSec will be a subset of aSec and section */ 9587 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9588 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9589 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9590 i[0] = 0; 9591 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9592 for (p = pStart; p < pEnd; p++) { 9593 PetscInt rDof, rOff, r; 9594 9595 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9596 if (!rDof) continue; 9597 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9598 if (numFields) { 9599 for (f = 0; f < numFields; f++) { 9600 annz = 0; 9601 for (r = 0; r < rDof; r++) { 9602 a = anchors[rOff + r]; 9603 if (a < sStart || a >= sEnd) continue; 9604 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9605 annz += aDof; 9606 } 9607 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9608 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9609 for (q = 0; q < dof; q++) { 9610 i[off + q + 1] = i[off + q] + annz; 9611 } 9612 } 9613 } else { 9614 annz = 0; 9615 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9616 for (q = 0; q < dof; q++) { 9617 a = anchors[rOff + q]; 9618 if (a < sStart || a >= sEnd) continue; 9619 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9620 annz += aDof; 9621 } 9622 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9623 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9624 for (q = 0; q < dof; q++) { 9625 i[off + q + 1] = i[off + q] + annz; 9626 } 9627 } 9628 } 9629 nnz = i[m]; 9630 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9631 offset = 0; 9632 for (p = pStart; p < pEnd; p++) { 9633 if (numFields) { 9634 for (f = 0; f < numFields; f++) { 9635 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9636 for (q = 0; q < dof; q++) { 9637 PetscInt rDof, rOff, r; 9638 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9639 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9640 for (r = 0; r < rDof; r++) { 9641 PetscInt s; 9642 9643 a = anchors[rOff + r]; 9644 if (a < sStart || a >= sEnd) continue; 9645 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9646 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9647 for (s = 0; s < aDof; s++) { 9648 j[offset++] = aOff + s; 9649 } 9650 } 9651 } 9652 } 9653 } else { 9654 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9655 for (q = 0; q < dof; q++) { 9656 PetscInt rDof, rOff, r; 9657 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9658 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9659 for (r = 0; r < rDof; r++) { 9660 PetscInt s; 9661 9662 a = anchors[rOff + r]; 9663 if (a < sStart || a >= sEnd) continue; 9664 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9665 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9666 for (s = 0; s < aDof; s++) { 9667 j[offset++] = aOff + s; 9668 } 9669 } 9670 } 9671 } 9672 } 9673 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9674 ierr = PetscFree(i);CHKERRQ(ierr); 9675 ierr = PetscFree(j);CHKERRQ(ierr); 9676 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9677 PetscFunctionReturn(0); 9678 } 9679 9680 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9681 { 9682 DM_Plex *plex = (DM_Plex *)dm->data; 9683 PetscSection anchorSection, section, cSec; 9684 Mat cMat; 9685 PetscErrorCode ierr; 9686 9687 PetscFunctionBegin; 9688 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9689 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9690 if (anchorSection) { 9691 PetscInt Nf; 9692 9693 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9694 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9695 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9696 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9697 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9698 ierr = DMSetDefaultConstraints(dm,cSec,cMat,NULL);CHKERRQ(ierr); 9699 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9700 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9701 } 9702 PetscFunctionReturn(0); 9703 } 9704 9705 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9706 { 9707 IS subis; 9708 PetscSection section, subsection; 9709 PetscErrorCode ierr; 9710 9711 PetscFunctionBegin; 9712 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9713 PetscCheckFalse(!section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9714 PetscCheckFalse(!subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9715 /* Create subdomain */ 9716 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9717 /* Create submodel */ 9718 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9719 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9720 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9721 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9722 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9723 /* Create map from submodel to global model */ 9724 if (is) { 9725 PetscSection sectionGlobal, subsectionGlobal; 9726 IS spIS; 9727 const PetscInt *spmap; 9728 PetscInt *subIndices; 9729 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9730 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9731 9732 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9733 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9734 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9735 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9736 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9737 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9738 for (p = pStart; p < pEnd; ++p) { 9739 PetscInt gdof, pSubSize = 0; 9740 9741 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9742 if (gdof > 0) { 9743 for (f = 0; f < Nf; ++f) { 9744 PetscInt fdof, fcdof; 9745 9746 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9747 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9748 pSubSize += fdof-fcdof; 9749 } 9750 subSize += pSubSize; 9751 if (pSubSize) { 9752 if (bs < 0) { 9753 bs = pSubSize; 9754 } else if (bs != pSubSize) { 9755 /* Layout does not admit a pointwise block size */ 9756 bs = 1; 9757 } 9758 } 9759 } 9760 } 9761 /* Must have same blocksize on all procs (some might have no points) */ 9762 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9763 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9764 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9765 else {bs = bsMinMax[0];} 9766 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9767 for (p = pStart; p < pEnd; ++p) { 9768 PetscInt gdof, goff; 9769 9770 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9771 if (gdof > 0) { 9772 const PetscInt point = spmap[p]; 9773 9774 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9775 for (f = 0; f < Nf; ++f) { 9776 PetscInt fdof, fcdof, fc, f2, poff = 0; 9777 9778 /* Can get rid of this loop by storing field information in the global section */ 9779 for (f2 = 0; f2 < f; ++f2) { 9780 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9781 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9782 poff += fdof-fcdof; 9783 } 9784 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9785 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9786 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9787 subIndices[subOff] = goff+poff+fc; 9788 } 9789 } 9790 } 9791 } 9792 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9793 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9794 if (bs > 1) { 9795 /* We need to check that the block size does not come from non-contiguous fields */ 9796 PetscInt i, j, set = 1; 9797 for (i = 0; i < subSize; i += bs) { 9798 for (j = 0; j < bs; ++j) { 9799 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9800 } 9801 } 9802 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9803 } 9804 /* Attach nullspace */ 9805 for (f = 0; f < Nf; ++f) { 9806 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9807 if ((*subdm)->nullspaceConstructors[f]) break; 9808 } 9809 if (f < Nf) { 9810 MatNullSpace nullSpace; 9811 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9812 9813 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9814 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9815 } 9816 } 9817 PetscFunctionReturn(0); 9818 } 9819 9820 /*@ 9821 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9822 9823 Input Parameter: 9824 - dm - The DM 9825 9826 Level: developer 9827 9828 Options Database Keys: 9829 . -dm_plex_monitor_throughput - Activate the monitor 9830 9831 .seealso: DMSetFromOptions(), DMPlexCreate() 9832 @*/ 9833 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9834 { 9835 #if defined(PETSC_USE_LOG) 9836 PetscStageLog stageLog; 9837 PetscLogEvent event; 9838 PetscLogStage stage; 9839 PetscEventPerfInfo eventInfo; 9840 PetscReal cellRate, flopRate; 9841 PetscInt cStart, cEnd, Nf, N; 9842 const char *name; 9843 PetscErrorCode ierr; 9844 #endif 9845 9846 PetscFunctionBegin; 9847 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9848 #if defined(PETSC_USE_LOG) 9849 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9850 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9851 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9852 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9853 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9854 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9855 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9856 N = (cEnd - cStart)*Nf*eventInfo.count; 9857 flopRate = eventInfo.flops/eventInfo.time; 9858 cellRate = N/eventInfo.time; 9859 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); 9860 #else 9861 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9862 #endif 9863 PetscFunctionReturn(0); 9864 } 9865