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 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2435 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2]; 2436 PetscInt pStart, pEnd, p, dof, cdof; 2437 2438 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2439 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2440 for (p = pStart; p < pEnd; ++p) { 2441 PetscInt bdof; 2442 2443 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2444 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2445 dof = dof < 0 ? -(dof+1) : dof; 2446 bdof = cdof && (dof-cdof) ? 1 : dof; 2447 if (dof) { 2448 if (bs < 0) {bs = bdof;} 2449 else if (bs != bdof) {bs = 1; break;} 2450 } 2451 } 2452 /* Must have same blocksize on all procs (some might have no points) */ 2453 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2454 bsLocal[1] = bs; 2455 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2456 if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2457 else bs = bsMinMax[0]; 2458 bs = PetscMax(1,bs); 2459 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2460 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2461 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2462 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2463 } 2464 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2465 PetscFunctionReturn(0); 2466 } 2467 2468 /*@ 2469 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2470 2471 Not collective 2472 2473 Input Parameter: 2474 . mesh - The DMPlex 2475 2476 Output Parameters: 2477 . subsection - The subdomain section 2478 2479 Level: developer 2480 2481 .seealso: 2482 @*/ 2483 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2484 { 2485 DM_Plex *mesh = (DM_Plex*) dm->data; 2486 PetscErrorCode ierr; 2487 2488 PetscFunctionBegin; 2489 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2490 if (!mesh->subdomainSection) { 2491 PetscSection section; 2492 PetscSF sf; 2493 2494 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2495 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2496 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2497 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2498 } 2499 *subsection = mesh->subdomainSection; 2500 PetscFunctionReturn(0); 2501 } 2502 2503 /*@ 2504 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2505 2506 Not collective 2507 2508 Input Parameter: 2509 . mesh - The DMPlex 2510 2511 Output Parameters: 2512 + pStart - The first mesh point 2513 - pEnd - The upper bound for mesh points 2514 2515 Level: beginner 2516 2517 .seealso: DMPlexCreate(), DMPlexSetChart() 2518 @*/ 2519 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2520 { 2521 DM_Plex *mesh = (DM_Plex*) dm->data; 2522 PetscErrorCode ierr; 2523 2524 PetscFunctionBegin; 2525 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2526 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2527 PetscFunctionReturn(0); 2528 } 2529 2530 /*@ 2531 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2532 2533 Not collective 2534 2535 Input Parameters: 2536 + mesh - The DMPlex 2537 . pStart - The first mesh point 2538 - pEnd - The upper bound for mesh points 2539 2540 Output Parameters: 2541 2542 Level: beginner 2543 2544 .seealso: DMPlexCreate(), DMPlexGetChart() 2545 @*/ 2546 PetscErrorCode DMPlexSetChart(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 = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2554 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2555 PetscFunctionReturn(0); 2556 } 2557 2558 /*@ 2559 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2560 2561 Not collective 2562 2563 Input Parameters: 2564 + mesh - The DMPlex 2565 - p - The point, which must lie in the chart set with DMPlexSetChart() 2566 2567 Output Parameter: 2568 . size - The cone size for point p 2569 2570 Level: beginner 2571 2572 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2573 @*/ 2574 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2575 { 2576 DM_Plex *mesh = (DM_Plex*) dm->data; 2577 PetscErrorCode ierr; 2578 2579 PetscFunctionBegin; 2580 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2581 PetscValidPointer(size, 3); 2582 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2583 PetscFunctionReturn(0); 2584 } 2585 2586 /*@ 2587 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2588 2589 Not collective 2590 2591 Input Parameters: 2592 + mesh - The DMPlex 2593 . p - The point, which must lie in the chart set with DMPlexSetChart() 2594 - size - The cone size for point p 2595 2596 Output Parameter: 2597 2598 Note: 2599 This should be called after DMPlexSetChart(). 2600 2601 Level: beginner 2602 2603 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2604 @*/ 2605 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2606 { 2607 DM_Plex *mesh = (DM_Plex*) dm->data; 2608 PetscErrorCode ierr; 2609 2610 PetscFunctionBegin; 2611 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2612 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2613 2614 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2615 PetscFunctionReturn(0); 2616 } 2617 2618 /*@ 2619 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2620 2621 Not collective 2622 2623 Input Parameters: 2624 + mesh - The DMPlex 2625 . p - The point, which must lie in the chart set with DMPlexSetChart() 2626 - size - The additional cone size for point p 2627 2628 Output Parameter: 2629 2630 Note: 2631 This should be called after DMPlexSetChart(). 2632 2633 Level: beginner 2634 2635 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2636 @*/ 2637 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2638 { 2639 DM_Plex *mesh = (DM_Plex*) dm->data; 2640 PetscInt csize; 2641 PetscErrorCode ierr; 2642 2643 PetscFunctionBegin; 2644 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2645 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2646 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2647 2648 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2649 PetscFunctionReturn(0); 2650 } 2651 2652 /*@C 2653 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2654 2655 Not collective 2656 2657 Input Parameters: 2658 + dm - The DMPlex 2659 - p - The point, which must lie in the chart set with DMPlexSetChart() 2660 2661 Output Parameter: 2662 . cone - An array of points which are on the in-edges for point p 2663 2664 Level: beginner 2665 2666 Fortran Notes: 2667 Since it returns an array, this routine is only available in Fortran 90, and you must 2668 include petsc.h90 in your code. 2669 You must also call DMPlexRestoreCone() after you finish using the returned array. 2670 DMPlexRestoreCone() is not needed/available in C. 2671 2672 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2673 @*/ 2674 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2675 { 2676 DM_Plex *mesh = (DM_Plex*) dm->data; 2677 PetscInt off; 2678 PetscErrorCode ierr; 2679 2680 PetscFunctionBegin; 2681 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2682 PetscValidPointer(cone, 3); 2683 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2684 *cone = &mesh->cones[off]; 2685 PetscFunctionReturn(0); 2686 } 2687 2688 /*@C 2689 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2690 2691 Not collective 2692 2693 Input Parameters: 2694 + dm - The DMPlex 2695 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2696 2697 Output Parameters: 2698 + pConesSection - PetscSection describing the layout of pCones 2699 - pCones - An array of points which are on the in-edges for the point set p 2700 2701 Level: intermediate 2702 2703 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2704 @*/ 2705 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2706 { 2707 PetscSection cs, newcs; 2708 PetscInt *cones; 2709 PetscInt *newarr=NULL; 2710 PetscInt n; 2711 PetscErrorCode ierr; 2712 2713 PetscFunctionBegin; 2714 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2715 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2716 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2717 if (pConesSection) *pConesSection = newcs; 2718 if (pCones) { 2719 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2720 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2721 } 2722 PetscFunctionReturn(0); 2723 } 2724 2725 /*@ 2726 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2727 2728 Not collective 2729 2730 Input Parameters: 2731 + dm - The DMPlex 2732 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2733 2734 Output Parameter: 2735 . expandedPoints - An array of vertices recursively expanded from input points 2736 2737 Level: advanced 2738 2739 Notes: 2740 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2741 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2742 2743 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2744 @*/ 2745 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2746 { 2747 IS *expandedPointsAll; 2748 PetscInt depth; 2749 PetscErrorCode ierr; 2750 2751 PetscFunctionBegin; 2752 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2753 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2754 PetscValidPointer(expandedPoints, 3); 2755 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2756 *expandedPoints = expandedPointsAll[0]; 2757 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2758 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2759 PetscFunctionReturn(0); 2760 } 2761 2762 /*@ 2763 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). 2764 2765 Not collective 2766 2767 Input Parameters: 2768 + dm - The DMPlex 2769 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2770 2771 Output Parameters: 2772 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2773 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2774 - sections - (optional) An array of sections which describe mappings from points to their cone points 2775 2776 Level: advanced 2777 2778 Notes: 2779 Like DMPlexGetConeTuple() but recursive. 2780 2781 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. 2782 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2783 2784 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: 2785 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2786 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2787 2788 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2789 @*/ 2790 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2791 { 2792 const PetscInt *arr0=NULL, *cone=NULL; 2793 PetscInt *arr=NULL, *newarr=NULL; 2794 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2795 IS *expandedPoints_; 2796 PetscSection *sections_; 2797 PetscErrorCode ierr; 2798 2799 PetscFunctionBegin; 2800 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2801 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2802 if (depth) PetscValidIntPointer(depth, 3); 2803 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2804 if (sections) PetscValidPointer(sections, 5); 2805 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2806 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2807 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2808 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2809 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2810 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2811 for (d=depth_-1; d>=0; d--) { 2812 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2813 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2814 for (i=0; i<n; i++) { 2815 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2816 if (arr[i] >= start && arr[i] < end) { 2817 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2818 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2819 } else { 2820 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2821 } 2822 } 2823 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2824 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2825 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2826 for (i=0; i<n; i++) { 2827 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2828 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2829 if (cn > 1) { 2830 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2831 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2832 } else { 2833 newarr[co] = arr[i]; 2834 } 2835 } 2836 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2837 arr = newarr; 2838 n = newn; 2839 } 2840 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2841 *depth = depth_; 2842 if (expandedPoints) *expandedPoints = expandedPoints_; 2843 else { 2844 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2845 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2846 } 2847 if (sections) *sections = sections_; 2848 else { 2849 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2850 ierr = PetscFree(sections_);CHKERRQ(ierr); 2851 } 2852 PetscFunctionReturn(0); 2853 } 2854 2855 /*@ 2856 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2857 2858 Not collective 2859 2860 Input Parameters: 2861 + dm - The DMPlex 2862 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2863 2864 Output Parameters: 2865 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2866 . expandedPoints - (optional) An array of recursively expanded cones 2867 - sections - (optional) An array of sections which describe mappings from points to their cone points 2868 2869 Level: advanced 2870 2871 Notes: 2872 See DMPlexGetConeRecursive() for details. 2873 2874 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2875 @*/ 2876 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2877 { 2878 PetscInt d, depth_; 2879 PetscErrorCode ierr; 2880 2881 PetscFunctionBegin; 2882 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2883 PetscCheckFalse(depth && *depth != depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2884 if (depth) *depth = 0; 2885 if (expandedPoints) { 2886 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2887 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2888 } 2889 if (sections) { 2890 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2891 ierr = PetscFree(*sections);CHKERRQ(ierr); 2892 } 2893 PetscFunctionReturn(0); 2894 } 2895 2896 /*@ 2897 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 2898 2899 Not collective 2900 2901 Input Parameters: 2902 + mesh - The DMPlex 2903 . p - The point, which must lie in the chart set with DMPlexSetChart() 2904 - cone - An array of points which are on the in-edges for point p 2905 2906 Output Parameter: 2907 2908 Note: 2909 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2910 2911 Level: beginner 2912 2913 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2914 @*/ 2915 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2916 { 2917 DM_Plex *mesh = (DM_Plex*) dm->data; 2918 PetscInt pStart, pEnd; 2919 PetscInt dof, off, c; 2920 PetscErrorCode ierr; 2921 2922 PetscFunctionBegin; 2923 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2924 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2925 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2926 if (dof) PetscValidPointer(cone, 3); 2927 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2928 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); 2929 for (c = 0; c < dof; ++c) { 2930 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); 2931 mesh->cones[off+c] = cone[c]; 2932 } 2933 PetscFunctionReturn(0); 2934 } 2935 2936 /*@C 2937 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2938 2939 Not collective 2940 2941 Input Parameters: 2942 + mesh - The DMPlex 2943 - p - The point, which must lie in the chart set with DMPlexSetChart() 2944 2945 Output Parameter: 2946 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2947 integer giving the prescription for cone traversal. 2948 2949 Level: beginner 2950 2951 Notes: 2952 The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 2953 the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 2954 of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 2955 with the identity. 2956 2957 Fortran Notes: 2958 Since it returns an array, this routine is only available in Fortran 90, and you must 2959 include petsc.h90 in your code. 2960 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2961 DMPlexRestoreConeOrientation() is not needed/available in C. 2962 2963 .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2964 @*/ 2965 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2966 { 2967 DM_Plex *mesh = (DM_Plex*) dm->data; 2968 PetscInt off; 2969 PetscErrorCode ierr; 2970 2971 PetscFunctionBegin; 2972 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2973 if (PetscDefined(USE_DEBUG)) { 2974 PetscInt dof; 2975 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2976 if (dof) PetscValidPointer(coneOrientation, 3); 2977 } 2978 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2979 2980 *coneOrientation = &mesh->coneOrientations[off]; 2981 PetscFunctionReturn(0); 2982 } 2983 2984 /*@ 2985 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2986 2987 Not collective 2988 2989 Input Parameters: 2990 + mesh - The DMPlex 2991 . p - The point, which must lie in the chart set with DMPlexSetChart() 2992 - coneOrientation - An array of orientations 2993 Output Parameter: 2994 2995 Notes: 2996 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2997 2998 The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 2999 3000 Level: beginner 3001 3002 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3003 @*/ 3004 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3005 { 3006 DM_Plex *mesh = (DM_Plex*) dm->data; 3007 PetscInt pStart, pEnd; 3008 PetscInt dof, off, c; 3009 PetscErrorCode ierr; 3010 3011 PetscFunctionBegin; 3012 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3013 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3014 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3015 if (dof) PetscValidPointer(coneOrientation, 3); 3016 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3017 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); 3018 for (c = 0; c < dof; ++c) { 3019 PetscInt cdof, o = coneOrientation[c]; 3020 3021 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 3022 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); 3023 mesh->coneOrientations[off+c] = o; 3024 } 3025 PetscFunctionReturn(0); 3026 } 3027 3028 /*@ 3029 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 3030 3031 Not collective 3032 3033 Input Parameters: 3034 + mesh - The DMPlex 3035 . p - The point, which must lie in the chart set with DMPlexSetChart() 3036 . conePos - The local index in the cone where the point should be put 3037 - conePoint - The mesh point to insert 3038 3039 Level: beginner 3040 3041 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3042 @*/ 3043 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3044 { 3045 DM_Plex *mesh = (DM_Plex*) dm->data; 3046 PetscInt pStart, pEnd; 3047 PetscInt dof, off; 3048 PetscErrorCode ierr; 3049 3050 PetscFunctionBegin; 3051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3052 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3053 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); 3054 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); 3055 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3056 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3057 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); 3058 mesh->cones[off+conePos] = conePoint; 3059 PetscFunctionReturn(0); 3060 } 3061 3062 /*@ 3063 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 3064 3065 Not collective 3066 3067 Input Parameters: 3068 + mesh - The DMPlex 3069 . p - The point, which must lie in the chart set with DMPlexSetChart() 3070 . conePos - The local index in the cone where the point should be put 3071 - coneOrientation - The point orientation to insert 3072 3073 Level: beginner 3074 3075 Notes: 3076 The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3077 3078 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3079 @*/ 3080 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3081 { 3082 DM_Plex *mesh = (DM_Plex*) dm->data; 3083 PetscInt pStart, pEnd; 3084 PetscInt dof, off; 3085 PetscErrorCode ierr; 3086 3087 PetscFunctionBegin; 3088 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3089 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3090 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); 3091 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3092 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3093 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); 3094 mesh->coneOrientations[off+conePos] = coneOrientation; 3095 PetscFunctionReturn(0); 3096 } 3097 3098 /*@ 3099 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3100 3101 Not collective 3102 3103 Input Parameters: 3104 + mesh - The DMPlex 3105 - p - The point, which must lie in the chart set with DMPlexSetChart() 3106 3107 Output Parameter: 3108 . size - The support size for point p 3109 3110 Level: beginner 3111 3112 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 3113 @*/ 3114 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3115 { 3116 DM_Plex *mesh = (DM_Plex*) dm->data; 3117 PetscErrorCode ierr; 3118 3119 PetscFunctionBegin; 3120 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3121 PetscValidPointer(size, 3); 3122 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3123 PetscFunctionReturn(0); 3124 } 3125 3126 /*@ 3127 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3128 3129 Not collective 3130 3131 Input Parameters: 3132 + mesh - The DMPlex 3133 . p - The point, which must lie in the chart set with DMPlexSetChart() 3134 - size - The support size for point p 3135 3136 Output Parameter: 3137 3138 Note: 3139 This should be called after DMPlexSetChart(). 3140 3141 Level: beginner 3142 3143 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 3144 @*/ 3145 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3146 { 3147 DM_Plex *mesh = (DM_Plex*) dm->data; 3148 PetscErrorCode ierr; 3149 3150 PetscFunctionBegin; 3151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3152 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3153 3154 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 3155 PetscFunctionReturn(0); 3156 } 3157 3158 /*@C 3159 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3160 3161 Not collective 3162 3163 Input Parameters: 3164 + mesh - The DMPlex 3165 - p - The point, which must lie in the chart set with DMPlexSetChart() 3166 3167 Output Parameter: 3168 . support - An array of points which are on the out-edges for point p 3169 3170 Level: beginner 3171 3172 Fortran Notes: 3173 Since it returns an array, this routine is only available in Fortran 90, and you must 3174 include petsc.h90 in your code. 3175 You must also call DMPlexRestoreSupport() after you finish using the returned array. 3176 DMPlexRestoreSupport() is not needed/available in C. 3177 3178 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 3179 @*/ 3180 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3181 { 3182 DM_Plex *mesh = (DM_Plex*) dm->data; 3183 PetscInt off; 3184 PetscErrorCode ierr; 3185 3186 PetscFunctionBegin; 3187 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3188 PetscValidPointer(support, 3); 3189 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3190 *support = &mesh->supports[off]; 3191 PetscFunctionReturn(0); 3192 } 3193 3194 /*@ 3195 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3196 3197 Not collective 3198 3199 Input Parameters: 3200 + mesh - The DMPlex 3201 . p - The point, which must lie in the chart set with DMPlexSetChart() 3202 - support - An array of points which are on the out-edges for point p 3203 3204 Output Parameter: 3205 3206 Note: 3207 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3208 3209 Level: beginner 3210 3211 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 3212 @*/ 3213 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3214 { 3215 DM_Plex *mesh = (DM_Plex*) dm->data; 3216 PetscInt pStart, pEnd; 3217 PetscInt dof, off, c; 3218 PetscErrorCode ierr; 3219 3220 PetscFunctionBegin; 3221 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3222 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3223 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3224 if (dof) PetscValidPointer(support, 3); 3225 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3226 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); 3227 for (c = 0; c < dof; ++c) { 3228 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); 3229 mesh->supports[off+c] = support[c]; 3230 } 3231 PetscFunctionReturn(0); 3232 } 3233 3234 /*@ 3235 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 3236 3237 Not collective 3238 3239 Input Parameters: 3240 + mesh - The DMPlex 3241 . p - The point, which must lie in the chart set with DMPlexSetChart() 3242 . supportPos - The local index in the cone where the point should be put 3243 - supportPoint - The mesh point to insert 3244 3245 Level: beginner 3246 3247 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3248 @*/ 3249 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3250 { 3251 DM_Plex *mesh = (DM_Plex*) dm->data; 3252 PetscInt pStart, pEnd; 3253 PetscInt dof, off; 3254 PetscErrorCode ierr; 3255 3256 PetscFunctionBegin; 3257 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3258 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3259 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3260 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3261 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); 3262 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); 3263 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); 3264 mesh->supports[off+supportPos] = supportPoint; 3265 PetscFunctionReturn(0); 3266 } 3267 3268 /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3269 PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3270 { 3271 switch (ct) { 3272 case DM_POLYTOPE_SEGMENT: 3273 if (o == -1) return -2; 3274 break; 3275 case DM_POLYTOPE_TRIANGLE: 3276 if (o == -3) return -1; 3277 if (o == -2) return -3; 3278 if (o == -1) return -2; 3279 break; 3280 case DM_POLYTOPE_QUADRILATERAL: 3281 if (o == -4) return -2; 3282 if (o == -3) return -1; 3283 if (o == -2) return -4; 3284 if (o == -1) return -3; 3285 break; 3286 default: return o; 3287 } 3288 return o; 3289 } 3290 3291 /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3292 PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3293 { 3294 switch (ct) { 3295 case DM_POLYTOPE_SEGMENT: 3296 if ((o == -2) || (o == 1)) return -1; 3297 if (o == -1) return 0; 3298 break; 3299 case DM_POLYTOPE_TRIANGLE: 3300 if (o == -3) return -2; 3301 if (o == -2) return -1; 3302 if (o == -1) return -3; 3303 break; 3304 case DM_POLYTOPE_QUADRILATERAL: 3305 if (o == -4) return -2; 3306 if (o == -3) return -1; 3307 if (o == -2) return -4; 3308 if (o == -1) return -3; 3309 break; 3310 default: return o; 3311 } 3312 return o; 3313 } 3314 3315 /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3316 PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3317 { 3318 PetscInt pStart, pEnd, p; 3319 PetscErrorCode ierr; 3320 3321 PetscFunctionBegin; 3322 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3323 for (p = pStart; p < pEnd; ++p) { 3324 const PetscInt *cone, *ornt; 3325 PetscInt coneSize, c; 3326 3327 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3328 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3329 ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr); 3330 for (c = 0; c < coneSize; ++c) { 3331 DMPolytopeType ct; 3332 const PetscInt o = ornt[c]; 3333 3334 ierr = DMPlexGetCellType(dm, cone[c], &ct);CHKERRQ(ierr); 3335 switch (ct) { 3336 case DM_POLYTOPE_SEGMENT: 3337 if ((o == -2) || (o == 1)) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3338 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, 0);CHKERRQ(ierr);} 3339 break; 3340 case DM_POLYTOPE_TRIANGLE: 3341 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3342 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3343 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3344 break; 3345 case DM_POLYTOPE_QUADRILATERAL: 3346 if (o == -4) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3347 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3348 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -4);CHKERRQ(ierr);} 3349 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3350 break; 3351 default: break; 3352 } 3353 } 3354 } 3355 PetscFunctionReturn(0); 3356 } 3357 3358 static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3359 { 3360 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3361 PetscInt *closure; 3362 const PetscInt *tmp = NULL, *tmpO = NULL; 3363 PetscInt off = 0, tmpSize, t; 3364 PetscErrorCode ierr; 3365 3366 PetscFunctionBeginHot; 3367 if (ornt) { 3368 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3369 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3370 } 3371 if (*points) { 3372 closure = *points; 3373 } else { 3374 PetscInt maxConeSize, maxSupportSize; 3375 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3376 ierr = DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure);CHKERRQ(ierr); 3377 } 3378 if (useCone) { 3379 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3380 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3381 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3382 } else { 3383 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3384 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3385 } 3386 if (ct == DM_POLYTOPE_UNKNOWN) { 3387 closure[off++] = p; 3388 closure[off++] = 0; 3389 for (t = 0; t < tmpSize; ++t) { 3390 closure[off++] = tmp[t]; 3391 closure[off++] = tmpO ? tmpO[t] : 0; 3392 } 3393 } else { 3394 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);CHKERRQ(ierr); 3395 3396 /* We assume that cells with a valid type have faces with a valid type */ 3397 closure[off++] = p; 3398 closure[off++] = ornt; 3399 for (t = 0; t < tmpSize; ++t) { 3400 DMPolytopeType ft; 3401 3402 ierr = DMPlexGetCellType(dm, tmp[t], &ft);CHKERRQ(ierr); 3403 closure[off++] = tmp[arr[t]]; 3404 closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3405 } 3406 } 3407 if (numPoints) *numPoints = tmpSize+1; 3408 if (points) *points = closure; 3409 PetscFunctionReturn(0); 3410 } 3411 3412 /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3413 static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3414 { 3415 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3416 const PetscInt *cone, *ornt; 3417 PetscInt *pts, *closure = NULL; 3418 DMPolytopeType ft; 3419 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3420 PetscInt dim, coneSize, c, d, clSize, cl; 3421 PetscErrorCode ierr; 3422 3423 PetscFunctionBeginHot; 3424 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3425 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 3426 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3427 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 3428 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3429 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3430 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3431 maxSize = PetscMax(coneSeries, supportSeries); 3432 if (*points) {pts = *points;} 3433 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts);CHKERRQ(ierr);} 3434 c = 0; 3435 pts[c++] = point; 3436 pts[c++] = o; 3437 ierr = DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft);CHKERRQ(ierr); 3438 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure);CHKERRQ(ierr); 3439 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3440 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure);CHKERRQ(ierr); 3441 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3442 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure);CHKERRQ(ierr); 3443 for (d = 2; d < coneSize; ++d) { 3444 ierr = DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft);CHKERRQ(ierr); 3445 pts[c++] = cone[arr[d*2+0]]; 3446 pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3447 } 3448 if (dim >= 3) { 3449 for (d = 2; d < coneSize; ++d) { 3450 const PetscInt fpoint = cone[arr[d*2+0]]; 3451 const PetscInt *fcone, *fornt; 3452 PetscInt fconeSize, fc, i; 3453 3454 ierr = DMPlexGetCellType(dm, fpoint, &ft);CHKERRQ(ierr); 3455 const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 3456 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 3457 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 3458 ierr = DMPlexGetConeOrientation(dm, fpoint, &fornt);CHKERRQ(ierr); 3459 for (fc = 0; fc < fconeSize; ++fc) { 3460 const PetscInt cp = fcone[farr[fc*2+0]]; 3461 const PetscInt co = farr[fc*2+1]; 3462 3463 for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3464 if (i == c) { 3465 ierr = DMPlexGetCellType(dm, cp, &ft);CHKERRQ(ierr); 3466 pts[c++] = cp; 3467 pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3468 } 3469 } 3470 } 3471 } 3472 *numPoints = c/2; 3473 *points = pts; 3474 PetscFunctionReturn(0); 3475 } 3476 3477 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3478 { 3479 DMPolytopeType ct; 3480 PetscInt *closure, *fifo; 3481 PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3482 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3483 PetscInt depth, maxSize; 3484 PetscErrorCode ierr; 3485 3486 PetscFunctionBeginHot; 3487 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3488 if (depth == 1) { 3489 ierr = DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3490 PetscFunctionReturn(0); 3491 } 3492 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3493 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3494 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 3495 ierr = DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3496 PetscFunctionReturn(0); 3497 } 3498 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3499 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3500 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3501 maxSize = PetscMax(coneSeries, supportSeries); 3502 ierr = DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3503 if (*points) {closure = *points;} 3504 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure);CHKERRQ(ierr);} 3505 closure[closureSize++] = p; 3506 closure[closureSize++] = ornt; 3507 fifo[fifoSize++] = p; 3508 fifo[fifoSize++] = ornt; 3509 fifo[fifoSize++] = ct; 3510 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3511 while (fifoSize - fifoStart) { 3512 const PetscInt q = fifo[fifoStart++]; 3513 const PetscInt o = fifo[fifoStart++]; 3514 const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3515 const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3516 const PetscInt *tmp, *tmpO; 3517 PetscInt tmpSize, t; 3518 3519 if (PetscDefined(USE_DEBUG)) { 3520 PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 3521 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); 3522 } 3523 if (useCone) { 3524 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3525 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3526 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3527 } else { 3528 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3529 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3530 tmpO = NULL; 3531 } 3532 for (t = 0; t < tmpSize; ++t) { 3533 const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3534 const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3535 const PetscInt cp = tmp[ip]; 3536 ierr = DMPlexGetCellType(dm, cp, &ct);CHKERRQ(ierr); 3537 const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3538 PetscInt c; 3539 3540 /* Check for duplicate */ 3541 for (c = 0; c < closureSize; c += 2) { 3542 if (closure[c] == cp) break; 3543 } 3544 if (c == closureSize) { 3545 closure[closureSize++] = cp; 3546 closure[closureSize++] = co; 3547 fifo[fifoSize++] = cp; 3548 fifo[fifoSize++] = co; 3549 fifo[fifoSize++] = ct; 3550 } 3551 } 3552 } 3553 ierr = DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3554 if (numPoints) *numPoints = closureSize/2; 3555 if (points) *points = closure; 3556 PetscFunctionReturn(0); 3557 } 3558 3559 /*@C 3560 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3561 3562 Not collective 3563 3564 Input Parameters: 3565 + dm - The DMPlex 3566 . p - The mesh point 3567 - useCone - PETSC_TRUE for the closure, otherwise return the star 3568 3569 Input/Output Parameter: 3570 . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 3571 if NULL on input, internal storage will be returned, otherwise the provided array is used 3572 3573 Output Parameter: 3574 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3575 3576 Note: 3577 If using internal storage (points is NULL on input), each call overwrites the last output. 3578 3579 Fortran Notes: 3580 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3581 3582 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3583 3584 Level: beginner 3585 3586 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3587 @*/ 3588 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3589 { 3590 PetscErrorCode ierr; 3591 3592 PetscFunctionBeginHot; 3593 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3594 if (numPoints) PetscValidIntPointer(numPoints, 4); 3595 if (points) PetscValidPointer(points, 5); 3596 ierr = DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points);CHKERRQ(ierr); 3597 PetscFunctionReturn(0); 3598 } 3599 3600 /*@C 3601 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3602 3603 Not collective 3604 3605 Input Parameters: 3606 + dm - The DMPlex 3607 . p - The mesh point 3608 . useCone - PETSC_TRUE for the closure, otherwise return the star 3609 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3610 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3611 3612 Note: 3613 If not using internal storage (points is not NULL on input), this call is unnecessary 3614 3615 Fortran Notes: 3616 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3617 3618 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3619 3620 Level: beginner 3621 3622 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3623 @*/ 3624 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3625 { 3626 PetscErrorCode ierr; 3627 3628 PetscFunctionBeginHot; 3629 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3630 if (numPoints) *numPoints = 0; 3631 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3632 PetscFunctionReturn(0); 3633 } 3634 3635 /*@ 3636 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3637 3638 Not collective 3639 3640 Input Parameter: 3641 . mesh - The DMPlex 3642 3643 Output Parameters: 3644 + maxConeSize - The maximum number of in-edges 3645 - maxSupportSize - The maximum number of out-edges 3646 3647 Level: beginner 3648 3649 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3650 @*/ 3651 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3652 { 3653 DM_Plex *mesh = (DM_Plex*) dm->data; 3654 3655 PetscFunctionBegin; 3656 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3657 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3658 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3659 PetscFunctionReturn(0); 3660 } 3661 3662 PetscErrorCode DMSetUp_Plex(DM dm) 3663 { 3664 DM_Plex *mesh = (DM_Plex*) dm->data; 3665 PetscInt size; 3666 PetscErrorCode ierr; 3667 3668 PetscFunctionBegin; 3669 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3670 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3671 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3672 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3673 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3674 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3675 if (mesh->maxSupportSize) { 3676 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3677 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3678 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3679 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3680 } 3681 PetscFunctionReturn(0); 3682 } 3683 3684 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3685 { 3686 PetscErrorCode ierr; 3687 3688 PetscFunctionBegin; 3689 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3690 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3691 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3692 if (dm->useNatural && dm->sfMigration) { 3693 PetscSF sfMigrationInv,sfNatural; 3694 PetscSection section, sectionSeq; 3695 3696 (*subdm)->sfMigration = dm->sfMigration; 3697 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3698 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3699 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3700 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3701 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3702 3703 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3704 (*subdm)->sfNatural = sfNatural; 3705 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3706 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3707 } 3708 PetscFunctionReturn(0); 3709 } 3710 3711 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3712 { 3713 PetscErrorCode ierr; 3714 PetscInt i = 0; 3715 3716 PetscFunctionBegin; 3717 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3718 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3719 (*superdm)->useNatural = PETSC_FALSE; 3720 for (i = 0; i < len; i++) { 3721 if (dms[i]->useNatural && dms[i]->sfMigration) { 3722 PetscSF sfMigrationInv,sfNatural; 3723 PetscSection section, sectionSeq; 3724 3725 (*superdm)->sfMigration = dms[i]->sfMigration; 3726 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3727 (*superdm)->useNatural = PETSC_TRUE; 3728 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3729 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3730 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3731 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3732 3733 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3734 (*superdm)->sfNatural = sfNatural; 3735 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3736 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3737 break; 3738 } 3739 } 3740 PetscFunctionReturn(0); 3741 } 3742 3743 /*@ 3744 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3745 3746 Not collective 3747 3748 Input Parameter: 3749 . mesh - The DMPlex 3750 3751 Output Parameter: 3752 3753 Note: 3754 This should be called after all calls to DMPlexSetCone() 3755 3756 Level: beginner 3757 3758 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3759 @*/ 3760 PetscErrorCode DMPlexSymmetrize(DM dm) 3761 { 3762 DM_Plex *mesh = (DM_Plex*) dm->data; 3763 PetscInt *offsets; 3764 PetscInt supportSize; 3765 PetscInt pStart, pEnd, p; 3766 PetscErrorCode ierr; 3767 3768 PetscFunctionBegin; 3769 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3770 PetscCheckFalse(mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3771 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3772 /* Calculate support sizes */ 3773 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3774 for (p = pStart; p < pEnd; ++p) { 3775 PetscInt dof, off, c; 3776 3777 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3778 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3779 for (c = off; c < off+dof; ++c) { 3780 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3781 } 3782 } 3783 for (p = pStart; p < pEnd; ++p) { 3784 PetscInt dof; 3785 3786 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3787 3788 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3789 } 3790 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3791 /* Calculate supports */ 3792 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3793 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3794 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3795 for (p = pStart; p < pEnd; ++p) { 3796 PetscInt dof, off, c; 3797 3798 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3799 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3800 for (c = off; c < off+dof; ++c) { 3801 const PetscInt q = mesh->cones[c]; 3802 PetscInt offS; 3803 3804 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3805 3806 mesh->supports[offS+offsets[q]] = p; 3807 ++offsets[q]; 3808 } 3809 } 3810 ierr = PetscFree(offsets);CHKERRQ(ierr); 3811 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3812 PetscFunctionReturn(0); 3813 } 3814 3815 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3816 { 3817 IS stratumIS; 3818 PetscErrorCode ierr; 3819 3820 PetscFunctionBegin; 3821 if (pStart >= pEnd) PetscFunctionReturn(0); 3822 if (PetscDefined(USE_DEBUG)) { 3823 PetscInt qStart, qEnd, numLevels, level; 3824 PetscBool overlap = PETSC_FALSE; 3825 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3826 for (level = 0; level < numLevels; level++) { 3827 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3828 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3829 } 3830 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); 3831 } 3832 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3833 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3834 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3835 PetscFunctionReturn(0); 3836 } 3837 3838 /*@ 3839 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3840 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3841 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3842 the DAG. 3843 3844 Collective on dm 3845 3846 Input Parameter: 3847 . mesh - The DMPlex 3848 3849 Output Parameter: 3850 3851 Notes: 3852 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3853 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3854 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3855 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3856 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3857 3858 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3859 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3860 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 3861 to interpolate only that one (e0), so that 3862 $ cone(c0) = {e0, v2} 3863 $ cone(e0) = {v0, v1} 3864 If DMPlexStratify() is run on this mesh, it will give depths 3865 $ depth 0 = {v0, v1, v2} 3866 $ depth 1 = {e0, c0} 3867 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3868 3869 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3870 3871 Level: beginner 3872 3873 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3874 @*/ 3875 PetscErrorCode DMPlexStratify(DM dm) 3876 { 3877 DM_Plex *mesh = (DM_Plex*) dm->data; 3878 DMLabel label; 3879 PetscInt pStart, pEnd, p; 3880 PetscInt numRoots = 0, numLeaves = 0; 3881 PetscErrorCode ierr; 3882 3883 PetscFunctionBegin; 3884 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3885 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3886 3887 /* Create depth label */ 3888 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3889 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3890 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3891 3892 { 3893 /* Initialize roots and count leaves */ 3894 PetscInt sMin = PETSC_MAX_INT; 3895 PetscInt sMax = PETSC_MIN_INT; 3896 PetscInt coneSize, supportSize; 3897 3898 for (p = pStart; p < pEnd; ++p) { 3899 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3900 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3901 if (!coneSize && supportSize) { 3902 sMin = PetscMin(p, sMin); 3903 sMax = PetscMax(p, sMax); 3904 ++numRoots; 3905 } else if (!supportSize && coneSize) { 3906 ++numLeaves; 3907 } else if (!supportSize && !coneSize) { 3908 /* Isolated points */ 3909 sMin = PetscMin(p, sMin); 3910 sMax = PetscMax(p, sMax); 3911 } 3912 } 3913 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3914 } 3915 3916 if (numRoots + numLeaves == (pEnd - pStart)) { 3917 PetscInt sMin = PETSC_MAX_INT; 3918 PetscInt sMax = PETSC_MIN_INT; 3919 PetscInt coneSize, supportSize; 3920 3921 for (p = pStart; p < pEnd; ++p) { 3922 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3923 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3924 if (!supportSize && coneSize) { 3925 sMin = PetscMin(p, sMin); 3926 sMax = PetscMax(p, sMax); 3927 } 3928 } 3929 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3930 } else { 3931 PetscInt level = 0; 3932 PetscInt qStart, qEnd, q; 3933 3934 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3935 while (qEnd > qStart) { 3936 PetscInt sMin = PETSC_MAX_INT; 3937 PetscInt sMax = PETSC_MIN_INT; 3938 3939 for (q = qStart; q < qEnd; ++q) { 3940 const PetscInt *support; 3941 PetscInt supportSize, s; 3942 3943 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3944 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3945 for (s = 0; s < supportSize; ++s) { 3946 sMin = PetscMin(support[s], sMin); 3947 sMax = PetscMax(support[s], sMax); 3948 } 3949 } 3950 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3951 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3952 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3953 } 3954 } 3955 { /* just in case there is an empty process */ 3956 PetscInt numValues, maxValues = 0, v; 3957 3958 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3959 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3960 for (v = numValues; v < maxValues; v++) { 3961 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3962 } 3963 } 3964 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3965 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3966 PetscFunctionReturn(0); 3967 } 3968 3969 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3970 { 3971 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3972 PetscInt dim, depth, pheight, coneSize; 3973 PetscErrorCode ierr; 3974 3975 PetscFunctionBeginHot; 3976 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3977 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3978 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3979 pheight = depth - pdepth; 3980 if (depth <= 1) { 3981 switch (pdepth) { 3982 case 0: ct = DM_POLYTOPE_POINT;break; 3983 case 1: 3984 switch (coneSize) { 3985 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3986 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3987 case 4: 3988 switch (dim) { 3989 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3990 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3991 default: break; 3992 } 3993 break; 3994 case 5: ct = DM_POLYTOPE_PYRAMID;break; 3995 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3996 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 3997 default: break; 3998 } 3999 } 4000 } else { 4001 if (pdepth == 0) { 4002 ct = DM_POLYTOPE_POINT; 4003 } else if (pheight == 0) { 4004 switch (dim) { 4005 case 1: 4006 switch (coneSize) { 4007 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4008 default: break; 4009 } 4010 break; 4011 case 2: 4012 switch (coneSize) { 4013 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4014 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4015 default: break; 4016 } 4017 break; 4018 case 3: 4019 switch (coneSize) { 4020 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 4021 case 5: 4022 { 4023 const PetscInt *cone; 4024 PetscInt faceConeSize; 4025 4026 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 4027 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 4028 switch (faceConeSize) { 4029 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4030 case 4: ct = DM_POLYTOPE_PYRAMID;break; 4031 } 4032 } 4033 break; 4034 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4035 default: break; 4036 } 4037 break; 4038 default: break; 4039 } 4040 } else if (pheight > 0) { 4041 switch (coneSize) { 4042 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4043 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4044 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4045 default: break; 4046 } 4047 } 4048 } 4049 *pt = ct; 4050 PetscFunctionReturn(0); 4051 } 4052 4053 /*@ 4054 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4055 4056 Collective on dm 4057 4058 Input Parameter: 4059 . mesh - The DMPlex 4060 4061 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4062 4063 Level: developer 4064 4065 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4066 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4067 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4068 4069 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 4070 @*/ 4071 PetscErrorCode DMPlexComputeCellTypes(DM dm) 4072 { 4073 DM_Plex *mesh; 4074 DMLabel ctLabel; 4075 PetscInt pStart, pEnd, p; 4076 PetscErrorCode ierr; 4077 4078 PetscFunctionBegin; 4079 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4080 mesh = (DM_Plex *) dm->data; 4081 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 4082 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 4083 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4084 for (p = pStart; p < pEnd; ++p) { 4085 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4086 PetscInt pdepth; 4087 4088 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 4089 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 4090 PetscCheckFalse(ct == DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 4091 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 4092 } 4093 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 4094 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 4095 PetscFunctionReturn(0); 4096 } 4097 4098 /*@C 4099 DMPlexGetJoin - Get an array for the join of the set of points 4100 4101 Not Collective 4102 4103 Input Parameters: 4104 + dm - The DMPlex object 4105 . numPoints - The number of input points for the join 4106 - points - The input points 4107 4108 Output Parameters: 4109 + numCoveredPoints - The number of points in the join 4110 - coveredPoints - The points in the join 4111 4112 Level: intermediate 4113 4114 Note: Currently, this is restricted to a single level join 4115 4116 Fortran Notes: 4117 Since it returns an array, this routine is only available in Fortran 90, and you must 4118 include petsc.h90 in your code. 4119 4120 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4121 4122 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 4123 @*/ 4124 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4125 { 4126 DM_Plex *mesh = (DM_Plex*) dm->data; 4127 PetscInt *join[2]; 4128 PetscInt joinSize, i = 0; 4129 PetscInt dof, off, p, c, m; 4130 PetscErrorCode ierr; 4131 4132 PetscFunctionBegin; 4133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4134 PetscValidIntPointer(points, 3); 4135 PetscValidIntPointer(numCoveredPoints, 4); 4136 PetscValidPointer(coveredPoints, 5); 4137 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4138 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4139 /* Copy in support of first point */ 4140 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 4141 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 4142 for (joinSize = 0; joinSize < dof; ++joinSize) { 4143 join[i][joinSize] = mesh->supports[off+joinSize]; 4144 } 4145 /* Check each successive support */ 4146 for (p = 1; p < numPoints; ++p) { 4147 PetscInt newJoinSize = 0; 4148 4149 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 4150 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 4151 for (c = 0; c < dof; ++c) { 4152 const PetscInt point = mesh->supports[off+c]; 4153 4154 for (m = 0; m < joinSize; ++m) { 4155 if (point == join[i][m]) { 4156 join[1-i][newJoinSize++] = point; 4157 break; 4158 } 4159 } 4160 } 4161 joinSize = newJoinSize; 4162 i = 1-i; 4163 } 4164 *numCoveredPoints = joinSize; 4165 *coveredPoints = join[i]; 4166 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4167 PetscFunctionReturn(0); 4168 } 4169 4170 /*@C 4171 DMPlexRestoreJoin - Restore an array for the join of the set of points 4172 4173 Not Collective 4174 4175 Input Parameters: 4176 + dm - The DMPlex object 4177 . numPoints - The number of input points for the join 4178 - points - The input points 4179 4180 Output Parameters: 4181 + numCoveredPoints - The number of points in the join 4182 - coveredPoints - The points in the join 4183 4184 Fortran Notes: 4185 Since it returns an array, this routine is only available in Fortran 90, and you must 4186 include petsc.h90 in your code. 4187 4188 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4189 4190 Level: intermediate 4191 4192 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 4193 @*/ 4194 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4195 { 4196 PetscErrorCode ierr; 4197 4198 PetscFunctionBegin; 4199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4200 if (points) PetscValidIntPointer(points,3); 4201 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4202 PetscValidPointer(coveredPoints, 5); 4203 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4204 if (numCoveredPoints) *numCoveredPoints = 0; 4205 PetscFunctionReturn(0); 4206 } 4207 4208 /*@C 4209 DMPlexGetFullJoin - Get an array for the join of the set of points 4210 4211 Not Collective 4212 4213 Input Parameters: 4214 + dm - The DMPlex object 4215 . numPoints - The number of input points for the join 4216 - points - The input points 4217 4218 Output Parameters: 4219 + numCoveredPoints - The number of points in the join 4220 - coveredPoints - The points in the join 4221 4222 Fortran Notes: 4223 Since it returns an array, this routine is only available in Fortran 90, and you must 4224 include petsc.h90 in your code. 4225 4226 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4227 4228 Level: intermediate 4229 4230 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 4231 @*/ 4232 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4233 { 4234 DM_Plex *mesh = (DM_Plex*) dm->data; 4235 PetscInt *offsets, **closures; 4236 PetscInt *join[2]; 4237 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 4238 PetscInt p, d, c, m, ms; 4239 PetscErrorCode ierr; 4240 4241 PetscFunctionBegin; 4242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4243 PetscValidIntPointer(points, 3); 4244 PetscValidIntPointer(numCoveredPoints, 4); 4245 PetscValidPointer(coveredPoints, 5); 4246 4247 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4248 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 4249 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4250 ms = mesh->maxSupportSize; 4251 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 4252 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4253 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4254 4255 for (p = 0; p < numPoints; ++p) { 4256 PetscInt closureSize; 4257 4258 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 4259 4260 offsets[p*(depth+2)+0] = 0; 4261 for (d = 0; d < depth+1; ++d) { 4262 PetscInt pStart, pEnd, i; 4263 4264 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4265 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4266 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4267 offsets[p*(depth+2)+d+1] = i; 4268 break; 4269 } 4270 } 4271 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4272 } 4273 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); 4274 } 4275 for (d = 0; d < depth+1; ++d) { 4276 PetscInt dof; 4277 4278 /* Copy in support of first point */ 4279 dof = offsets[d+1] - offsets[d]; 4280 for (joinSize = 0; joinSize < dof; ++joinSize) { 4281 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4282 } 4283 /* Check each successive cone */ 4284 for (p = 1; p < numPoints && joinSize; ++p) { 4285 PetscInt newJoinSize = 0; 4286 4287 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4288 for (c = 0; c < dof; ++c) { 4289 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4290 4291 for (m = 0; m < joinSize; ++m) { 4292 if (point == join[i][m]) { 4293 join[1-i][newJoinSize++] = point; 4294 break; 4295 } 4296 } 4297 } 4298 joinSize = newJoinSize; 4299 i = 1-i; 4300 } 4301 if (joinSize) break; 4302 } 4303 *numCoveredPoints = joinSize; 4304 *coveredPoints = join[i]; 4305 for (p = 0; p < numPoints; ++p) { 4306 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4307 } 4308 ierr = PetscFree(closures);CHKERRQ(ierr); 4309 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4310 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4311 PetscFunctionReturn(0); 4312 } 4313 4314 /*@C 4315 DMPlexGetMeet - Get an array for the meet of the set of points 4316 4317 Not Collective 4318 4319 Input Parameters: 4320 + dm - The DMPlex object 4321 . numPoints - The number of input points for the meet 4322 - points - The input points 4323 4324 Output Parameters: 4325 + numCoveredPoints - The number of points in the meet 4326 - coveredPoints - The points in the meet 4327 4328 Level: intermediate 4329 4330 Note: Currently, this is restricted to a single level meet 4331 4332 Fortran Notes: 4333 Since it returns an array, this routine is only available in Fortran 90, and you must 4334 include petsc.h90 in your code. 4335 4336 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4337 4338 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4339 @*/ 4340 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4341 { 4342 DM_Plex *mesh = (DM_Plex*) dm->data; 4343 PetscInt *meet[2]; 4344 PetscInt meetSize, i = 0; 4345 PetscInt dof, off, p, c, m; 4346 PetscErrorCode ierr; 4347 4348 PetscFunctionBegin; 4349 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4350 PetscValidPointer(points, 3); 4351 PetscValidPointer(numCoveringPoints, 4); 4352 PetscValidPointer(coveringPoints, 5); 4353 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4354 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4355 /* Copy in cone of first point */ 4356 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4357 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4358 for (meetSize = 0; meetSize < dof; ++meetSize) { 4359 meet[i][meetSize] = mesh->cones[off+meetSize]; 4360 } 4361 /* Check each successive cone */ 4362 for (p = 1; p < numPoints; ++p) { 4363 PetscInt newMeetSize = 0; 4364 4365 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4366 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4367 for (c = 0; c < dof; ++c) { 4368 const PetscInt point = mesh->cones[off+c]; 4369 4370 for (m = 0; m < meetSize; ++m) { 4371 if (point == meet[i][m]) { 4372 meet[1-i][newMeetSize++] = point; 4373 break; 4374 } 4375 } 4376 } 4377 meetSize = newMeetSize; 4378 i = 1-i; 4379 } 4380 *numCoveringPoints = meetSize; 4381 *coveringPoints = meet[i]; 4382 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4383 PetscFunctionReturn(0); 4384 } 4385 4386 /*@C 4387 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4388 4389 Not Collective 4390 4391 Input Parameters: 4392 + dm - The DMPlex object 4393 . numPoints - The number of input points for the meet 4394 - points - The input points 4395 4396 Output Parameters: 4397 + numCoveredPoints - The number of points in the meet 4398 - coveredPoints - The points in the meet 4399 4400 Level: intermediate 4401 4402 Fortran Notes: 4403 Since it returns an array, this routine is only available in Fortran 90, and you must 4404 include petsc.h90 in your code. 4405 4406 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4407 4408 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4409 @*/ 4410 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4411 { 4412 PetscErrorCode ierr; 4413 4414 PetscFunctionBegin; 4415 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4416 if (points) PetscValidIntPointer(points,3); 4417 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4418 PetscValidPointer(coveredPoints,5); 4419 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4420 if (numCoveredPoints) *numCoveredPoints = 0; 4421 PetscFunctionReturn(0); 4422 } 4423 4424 /*@C 4425 DMPlexGetFullMeet - Get an array for the meet of the set of points 4426 4427 Not Collective 4428 4429 Input Parameters: 4430 + dm - The DMPlex object 4431 . numPoints - The number of input points for the meet 4432 - points - The input points 4433 4434 Output Parameters: 4435 + numCoveredPoints - The number of points in the meet 4436 - coveredPoints - The points in the meet 4437 4438 Level: intermediate 4439 4440 Fortran Notes: 4441 Since it returns an array, this routine is only available in Fortran 90, and you must 4442 include petsc.h90 in your code. 4443 4444 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4445 4446 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4447 @*/ 4448 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4449 { 4450 DM_Plex *mesh = (DM_Plex*) dm->data; 4451 PetscInt *offsets, **closures; 4452 PetscInt *meet[2]; 4453 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4454 PetscInt p, h, c, m, mc; 4455 PetscErrorCode ierr; 4456 4457 PetscFunctionBegin; 4458 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4459 PetscValidPointer(points, 3); 4460 PetscValidPointer(numCoveredPoints, 4); 4461 PetscValidPointer(coveredPoints, 5); 4462 4463 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4464 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4465 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4466 mc = mesh->maxConeSize; 4467 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4468 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4469 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4470 4471 for (p = 0; p < numPoints; ++p) { 4472 PetscInt closureSize; 4473 4474 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4475 4476 offsets[p*(height+2)+0] = 0; 4477 for (h = 0; h < height+1; ++h) { 4478 PetscInt pStart, pEnd, i; 4479 4480 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4481 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4482 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4483 offsets[p*(height+2)+h+1] = i; 4484 break; 4485 } 4486 } 4487 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4488 } 4489 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); 4490 } 4491 for (h = 0; h < height+1; ++h) { 4492 PetscInt dof; 4493 4494 /* Copy in cone of first point */ 4495 dof = offsets[h+1] - offsets[h]; 4496 for (meetSize = 0; meetSize < dof; ++meetSize) { 4497 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4498 } 4499 /* Check each successive cone */ 4500 for (p = 1; p < numPoints && meetSize; ++p) { 4501 PetscInt newMeetSize = 0; 4502 4503 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4504 for (c = 0; c < dof; ++c) { 4505 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4506 4507 for (m = 0; m < meetSize; ++m) { 4508 if (point == meet[i][m]) { 4509 meet[1-i][newMeetSize++] = point; 4510 break; 4511 } 4512 } 4513 } 4514 meetSize = newMeetSize; 4515 i = 1-i; 4516 } 4517 if (meetSize) break; 4518 } 4519 *numCoveredPoints = meetSize; 4520 *coveredPoints = meet[i]; 4521 for (p = 0; p < numPoints; ++p) { 4522 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4523 } 4524 ierr = PetscFree(closures);CHKERRQ(ierr); 4525 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4526 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4527 PetscFunctionReturn(0); 4528 } 4529 4530 /*@C 4531 DMPlexEqual - Determine if two DMs have the same topology 4532 4533 Not Collective 4534 4535 Input Parameters: 4536 + dmA - A DMPlex object 4537 - dmB - A DMPlex object 4538 4539 Output Parameters: 4540 . equal - PETSC_TRUE if the topologies are identical 4541 4542 Level: intermediate 4543 4544 Notes: 4545 We are not solving graph isomorphism, so we do not permutation. 4546 4547 .seealso: DMPlexGetCone() 4548 @*/ 4549 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4550 { 4551 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4552 PetscErrorCode ierr; 4553 4554 PetscFunctionBegin; 4555 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4556 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4557 PetscValidPointer(equal, 3); 4558 4559 *equal = PETSC_FALSE; 4560 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4561 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4562 if (depth != depthB) PetscFunctionReturn(0); 4563 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4564 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4565 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4566 for (p = pStart; p < pEnd; ++p) { 4567 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4568 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4569 4570 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4571 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4572 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4573 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4574 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4575 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4576 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4577 for (c = 0; c < coneSize; ++c) { 4578 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4579 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4580 } 4581 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4582 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4583 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4584 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4585 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4586 for (s = 0; s < supportSize; ++s) { 4587 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4588 } 4589 } 4590 *equal = PETSC_TRUE; 4591 PetscFunctionReturn(0); 4592 } 4593 4594 /*@C 4595 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4596 4597 Not Collective 4598 4599 Input Parameters: 4600 + dm - The DMPlex 4601 . cellDim - The cell dimension 4602 - numCorners - The number of vertices on a cell 4603 4604 Output Parameters: 4605 . numFaceVertices - The number of vertices on a face 4606 4607 Level: developer 4608 4609 Notes: 4610 Of course this can only work for a restricted set of symmetric shapes 4611 4612 .seealso: DMPlexGetCone() 4613 @*/ 4614 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4615 { 4616 MPI_Comm comm; 4617 PetscErrorCode ierr; 4618 4619 PetscFunctionBegin; 4620 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4621 PetscValidPointer(numFaceVertices,4); 4622 switch (cellDim) { 4623 case 0: 4624 *numFaceVertices = 0; 4625 break; 4626 case 1: 4627 *numFaceVertices = 1; 4628 break; 4629 case 2: 4630 switch (numCorners) { 4631 case 3: /* triangle */ 4632 *numFaceVertices = 2; /* Edge has 2 vertices */ 4633 break; 4634 case 4: /* quadrilateral */ 4635 *numFaceVertices = 2; /* Edge has 2 vertices */ 4636 break; 4637 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4638 *numFaceVertices = 3; /* Edge has 3 vertices */ 4639 break; 4640 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4641 *numFaceVertices = 3; /* Edge has 3 vertices */ 4642 break; 4643 default: 4644 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4645 } 4646 break; 4647 case 3: 4648 switch (numCorners) { 4649 case 4: /* tetradehdron */ 4650 *numFaceVertices = 3; /* Face has 3 vertices */ 4651 break; 4652 case 6: /* tet cohesive cells */ 4653 *numFaceVertices = 4; /* Face has 4 vertices */ 4654 break; 4655 case 8: /* hexahedron */ 4656 *numFaceVertices = 4; /* Face has 4 vertices */ 4657 break; 4658 case 9: /* tet cohesive Lagrange cells */ 4659 *numFaceVertices = 6; /* Face has 6 vertices */ 4660 break; 4661 case 10: /* quadratic tetrahedron */ 4662 *numFaceVertices = 6; /* Face has 6 vertices */ 4663 break; 4664 case 12: /* hex cohesive Lagrange cells */ 4665 *numFaceVertices = 6; /* Face has 6 vertices */ 4666 break; 4667 case 18: /* quadratic tet cohesive Lagrange cells */ 4668 *numFaceVertices = 6; /* Face has 6 vertices */ 4669 break; 4670 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4671 *numFaceVertices = 9; /* Face has 9 vertices */ 4672 break; 4673 default: 4674 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4675 } 4676 break; 4677 default: 4678 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4679 } 4680 PetscFunctionReturn(0); 4681 } 4682 4683 /*@ 4684 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4685 4686 Not Collective 4687 4688 Input Parameter: 4689 . dm - The DMPlex object 4690 4691 Output Parameter: 4692 . depthLabel - The DMLabel recording point depth 4693 4694 Level: developer 4695 4696 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4697 @*/ 4698 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4699 { 4700 PetscFunctionBegin; 4701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4702 PetscValidPointer(depthLabel, 2); 4703 *depthLabel = dm->depthLabel; 4704 PetscFunctionReturn(0); 4705 } 4706 4707 /*@ 4708 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4709 4710 Not Collective 4711 4712 Input Parameter: 4713 . dm - The DMPlex object 4714 4715 Output Parameter: 4716 . depth - The number of strata (breadth first levels) in the DAG 4717 4718 Level: developer 4719 4720 Notes: 4721 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4722 The point depth is described more in detail in DMPlexGetDepthStratum(). 4723 An empty mesh gives -1. 4724 4725 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4726 @*/ 4727 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4728 { 4729 DMLabel label; 4730 PetscInt d = 0; 4731 PetscErrorCode ierr; 4732 4733 PetscFunctionBegin; 4734 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4735 PetscValidPointer(depth, 2); 4736 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4737 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4738 *depth = d-1; 4739 PetscFunctionReturn(0); 4740 } 4741 4742 /*@ 4743 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4744 4745 Not Collective 4746 4747 Input Parameters: 4748 + dm - The DMPlex object 4749 - stratumValue - The requested depth 4750 4751 Output Parameters: 4752 + start - The first point at this depth 4753 - end - One beyond the last point at this depth 4754 4755 Notes: 4756 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4757 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4758 higher dimension, e.g., "edges". 4759 4760 Level: developer 4761 4762 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4763 @*/ 4764 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4765 { 4766 DMLabel label; 4767 PetscInt pStart, pEnd; 4768 PetscErrorCode ierr; 4769 4770 PetscFunctionBegin; 4771 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4772 if (start) {PetscValidPointer(start, 3); *start = 0;} 4773 if (end) {PetscValidPointer(end, 4); *end = 0;} 4774 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4775 if (pStart == pEnd) PetscFunctionReturn(0); 4776 if (stratumValue < 0) { 4777 if (start) *start = pStart; 4778 if (end) *end = pEnd; 4779 PetscFunctionReturn(0); 4780 } 4781 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4782 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4783 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4784 PetscFunctionReturn(0); 4785 } 4786 4787 /*@ 4788 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4789 4790 Not Collective 4791 4792 Input Parameters: 4793 + dm - The DMPlex object 4794 - stratumValue - The requested height 4795 4796 Output Parameters: 4797 + start - The first point at this height 4798 - end - One beyond the last point at this height 4799 4800 Notes: 4801 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4802 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4803 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4804 4805 Level: developer 4806 4807 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4808 @*/ 4809 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4810 { 4811 DMLabel label; 4812 PetscInt depth, pStart, pEnd; 4813 PetscErrorCode ierr; 4814 4815 PetscFunctionBegin; 4816 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4817 if (start) {PetscValidPointer(start, 3); *start = 0;} 4818 if (end) {PetscValidPointer(end, 4); *end = 0;} 4819 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4820 if (pStart == pEnd) PetscFunctionReturn(0); 4821 if (stratumValue < 0) { 4822 if (start) *start = pStart; 4823 if (end) *end = pEnd; 4824 PetscFunctionReturn(0); 4825 } 4826 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4827 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4828 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4829 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4830 PetscFunctionReturn(0); 4831 } 4832 4833 /*@ 4834 DMPlexGetPointDepth - Get the depth of a given point 4835 4836 Not Collective 4837 4838 Input Parameters: 4839 + dm - The DMPlex object 4840 - point - The point 4841 4842 Output Parameter: 4843 . depth - The depth of the point 4844 4845 Level: intermediate 4846 4847 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4848 @*/ 4849 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4850 { 4851 PetscErrorCode ierr; 4852 4853 PetscFunctionBegin; 4854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4855 PetscValidIntPointer(depth, 3); 4856 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4857 PetscFunctionReturn(0); 4858 } 4859 4860 /*@ 4861 DMPlexGetPointHeight - Get the height 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 . height - The height of the point 4871 4872 Level: intermediate 4873 4874 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4875 @*/ 4876 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4877 { 4878 PetscInt n, pDepth; 4879 PetscErrorCode ierr; 4880 4881 PetscFunctionBegin; 4882 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4883 PetscValidIntPointer(height, 3); 4884 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4885 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4886 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4887 PetscFunctionReturn(0); 4888 } 4889 4890 /*@ 4891 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4892 4893 Not Collective 4894 4895 Input Parameter: 4896 . dm - The DMPlex object 4897 4898 Output Parameter: 4899 . celltypeLabel - The DMLabel recording cell polytope type 4900 4901 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4902 DMCreateLabel(dm, "celltype") beforehand. 4903 4904 Level: developer 4905 4906 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4907 @*/ 4908 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4909 { 4910 PetscErrorCode ierr; 4911 4912 PetscFunctionBegin; 4913 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4914 PetscValidPointer(celltypeLabel, 2); 4915 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4916 *celltypeLabel = dm->celltypeLabel; 4917 PetscFunctionReturn(0); 4918 } 4919 4920 /*@ 4921 DMPlexGetCellType - Get the polytope type of a given cell 4922 4923 Not Collective 4924 4925 Input Parameters: 4926 + dm - The DMPlex object 4927 - cell - The cell 4928 4929 Output Parameter: 4930 . celltype - The polytope type of the cell 4931 4932 Level: intermediate 4933 4934 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4935 @*/ 4936 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4937 { 4938 DMLabel label; 4939 PetscInt ct; 4940 PetscErrorCode ierr; 4941 4942 PetscFunctionBegin; 4943 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4944 PetscValidPointer(celltype, 3); 4945 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4946 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4947 PetscCheckFalse(ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4948 *celltype = (DMPolytopeType) ct; 4949 PetscFunctionReturn(0); 4950 } 4951 4952 /*@ 4953 DMPlexSetCellType - Set the polytope type of a given cell 4954 4955 Not Collective 4956 4957 Input Parameters: 4958 + dm - The DMPlex object 4959 . cell - The cell 4960 - celltype - The polytope type of the cell 4961 4962 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4963 is executed. This function will override the computed type. However, if automatic classification will not succeed 4964 and a user wants to manually specify all types, the classification must be disabled by calling 4965 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4966 4967 Level: advanced 4968 4969 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4970 @*/ 4971 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4972 { 4973 DMLabel label; 4974 PetscErrorCode ierr; 4975 4976 PetscFunctionBegin; 4977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4978 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4979 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 4980 PetscFunctionReturn(0); 4981 } 4982 4983 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4984 { 4985 PetscSection section, s; 4986 Mat m; 4987 PetscInt maxHeight; 4988 PetscErrorCode ierr; 4989 4990 PetscFunctionBegin; 4991 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4992 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 4993 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 4994 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4995 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 4996 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4997 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 4998 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 4999 ierr = DMSetDefaultConstraints(*cdm, s, m, NULL);CHKERRQ(ierr); 5000 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 5001 ierr = MatDestroy(&m);CHKERRQ(ierr); 5002 5003 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 5004 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 5005 PetscFunctionReturn(0); 5006 } 5007 5008 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5009 { 5010 Vec coordsLocal; 5011 DM coordsDM; 5012 PetscErrorCode ierr; 5013 5014 PetscFunctionBegin; 5015 *field = NULL; 5016 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 5017 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 5018 if (coordsLocal && coordsDM) { 5019 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 5020 } 5021 PetscFunctionReturn(0); 5022 } 5023 5024 /*@C 5025 DMPlexGetConeSection - Return a section which describes the layout of cone data 5026 5027 Not Collective 5028 5029 Input Parameters: 5030 . dm - The DMPlex object 5031 5032 Output Parameter: 5033 . section - The PetscSection object 5034 5035 Level: developer 5036 5037 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 5038 @*/ 5039 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5040 { 5041 DM_Plex *mesh = (DM_Plex*) dm->data; 5042 5043 PetscFunctionBegin; 5044 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5045 if (section) *section = mesh->coneSection; 5046 PetscFunctionReturn(0); 5047 } 5048 5049 /*@C 5050 DMPlexGetSupportSection - Return a section which describes the layout of support data 5051 5052 Not Collective 5053 5054 Input Parameters: 5055 . dm - The DMPlex object 5056 5057 Output Parameter: 5058 . section - The PetscSection object 5059 5060 Level: developer 5061 5062 .seealso: DMPlexGetConeSection() 5063 @*/ 5064 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5065 { 5066 DM_Plex *mesh = (DM_Plex*) dm->data; 5067 5068 PetscFunctionBegin; 5069 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5070 if (section) *section = mesh->supportSection; 5071 PetscFunctionReturn(0); 5072 } 5073 5074 /*@C 5075 DMPlexGetCones - Return cone data 5076 5077 Not Collective 5078 5079 Input Parameters: 5080 . dm - The DMPlex object 5081 5082 Output Parameter: 5083 . cones - The cone for each point 5084 5085 Level: developer 5086 5087 .seealso: DMPlexGetConeSection() 5088 @*/ 5089 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5090 { 5091 DM_Plex *mesh = (DM_Plex*) dm->data; 5092 5093 PetscFunctionBegin; 5094 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5095 if (cones) *cones = mesh->cones; 5096 PetscFunctionReturn(0); 5097 } 5098 5099 /*@C 5100 DMPlexGetConeOrientations - Return cone orientation data 5101 5102 Not Collective 5103 5104 Input Parameters: 5105 . dm - The DMPlex object 5106 5107 Output Parameter: 5108 . coneOrientations - The array of cone orientations for all points 5109 5110 Level: developer 5111 5112 Notes: 5113 The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5114 5115 The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5116 5117 .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation() 5118 @*/ 5119 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5120 { 5121 DM_Plex *mesh = (DM_Plex*) dm->data; 5122 5123 PetscFunctionBegin; 5124 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5125 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5126 PetscFunctionReturn(0); 5127 } 5128 5129 /******************************** FEM Support **********************************/ 5130 5131 /* 5132 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 5133 representing a line in the section. 5134 */ 5135 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 5136 { 5137 PetscErrorCode ierr; 5138 5139 PetscFunctionBeginHot; 5140 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 5141 if (line < 0) { 5142 *k = 0; 5143 *Nc = 0; 5144 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 5145 *k = 1; 5146 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 5147 /* An order k SEM disc has k-1 dofs on an edge */ 5148 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 5149 *k = *k / *Nc + 1; 5150 } 5151 PetscFunctionReturn(0); 5152 } 5153 5154 /*@ 5155 5156 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5157 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 5158 section provided (or the section of the DM). 5159 5160 Input Parameters: 5161 + dm - The DM 5162 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5163 - section - The PetscSection to reorder, or NULL for the default section 5164 5165 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5166 degree of the basis. 5167 5168 Example: 5169 A typical interpolated single-quad mesh might order points as 5170 .vb 5171 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5172 5173 v4 -- e6 -- v3 5174 | | 5175 e7 c0 e8 5176 | | 5177 v1 -- e5 -- v2 5178 .ve 5179 5180 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5181 dofs in the order of points, e.g., 5182 .vb 5183 c0 -> [0,1,2,3] 5184 v1 -> [4] 5185 ... 5186 e5 -> [8, 9] 5187 .ve 5188 5189 which corresponds to the dofs 5190 .vb 5191 6 10 11 7 5192 13 2 3 15 5193 12 0 1 14 5194 4 8 9 5 5195 .ve 5196 5197 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5198 .vb 5199 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5200 .ve 5201 5202 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5203 .vb 5204 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5205 .ve 5206 5207 Level: developer 5208 5209 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 5210 @*/ 5211 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5212 { 5213 DMLabel label; 5214 PetscInt dim, depth = -1, eStart = -1, Nf; 5215 PetscBool vertexchart; 5216 PetscErrorCode ierr; 5217 5218 PetscFunctionBegin; 5219 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5220 if (dim < 1) PetscFunctionReturn(0); 5221 if (point < 0) { 5222 PetscInt sStart,sEnd; 5223 5224 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 5225 point = sEnd-sStart ? sStart : point; 5226 } 5227 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 5228 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 5229 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5230 if (depth == 1) {eStart = point;} 5231 else if (depth == dim) { 5232 const PetscInt *cone; 5233 5234 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5235 if (dim == 2) eStart = cone[0]; 5236 else if (dim == 3) { 5237 const PetscInt *cone2; 5238 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 5239 eStart = cone2[0]; 5240 } 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); 5241 } 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); 5242 { /* Determine whether the chart covers all points or just vertices. */ 5243 PetscInt pStart,pEnd,cStart,cEnd; 5244 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 5245 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 5246 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5247 else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5248 else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 5249 } 5250 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5251 for (PetscInt d=1; d<=dim; d++) { 5252 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5253 PetscInt *perm; 5254 5255 for (f = 0; f < Nf; ++f) { 5256 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5257 size += PetscPowInt(k+1, d)*Nc; 5258 } 5259 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 5260 for (f = 0; f < Nf; ++f) { 5261 switch (d) { 5262 case 1: 5263 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5264 /* 5265 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5266 We want [ vtx0; edge of length k-1; vtx1 ] 5267 */ 5268 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5269 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5270 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5271 foffset = offset; 5272 break; 5273 case 2: 5274 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5275 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5276 /* The SEM order is 5277 5278 v_lb, {e_b}, v_rb, 5279 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5280 v_lt, reverse {e_t}, v_rt 5281 */ 5282 { 5283 const PetscInt of = 0; 5284 const PetscInt oeb = of + PetscSqr(k-1); 5285 const PetscInt oer = oeb + (k-1); 5286 const PetscInt oet = oer + (k-1); 5287 const PetscInt oel = oet + (k-1); 5288 const PetscInt ovlb = oel + (k-1); 5289 const PetscInt ovrb = ovlb + 1; 5290 const PetscInt ovrt = ovrb + 1; 5291 const PetscInt ovlt = ovrt + 1; 5292 PetscInt o; 5293 5294 /* bottom */ 5295 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5296 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5297 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5298 /* middle */ 5299 for (i = 0; i < k-1; ++i) { 5300 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5301 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; 5302 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5303 } 5304 /* top */ 5305 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5306 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5307 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5308 foffset = offset; 5309 } 5310 break; 5311 case 3: 5312 /* The original hex closure is 5313 5314 {c, 5315 f_b, f_t, f_f, f_b, f_r, f_l, 5316 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5317 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5318 */ 5319 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5320 /* The SEM order is 5321 Bottom Slice 5322 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5323 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5324 v_blb, {e_bb}, v_brb, 5325 5326 Middle Slice (j) 5327 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5328 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5329 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5330 5331 Top Slice 5332 v_tlf, {e_tf}, v_trf, 5333 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5334 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5335 */ 5336 { 5337 const PetscInt oc = 0; 5338 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5339 const PetscInt oft = ofb + PetscSqr(k-1); 5340 const PetscInt off = oft + PetscSqr(k-1); 5341 const PetscInt ofk = off + PetscSqr(k-1); 5342 const PetscInt ofr = ofk + PetscSqr(k-1); 5343 const PetscInt ofl = ofr + PetscSqr(k-1); 5344 const PetscInt oebl = ofl + PetscSqr(k-1); 5345 const PetscInt oebb = oebl + (k-1); 5346 const PetscInt oebr = oebb + (k-1); 5347 const PetscInt oebf = oebr + (k-1); 5348 const PetscInt oetf = oebf + (k-1); 5349 const PetscInt oetr = oetf + (k-1); 5350 const PetscInt oetb = oetr + (k-1); 5351 const PetscInt oetl = oetb + (k-1); 5352 const PetscInt oerf = oetl + (k-1); 5353 const PetscInt oelf = oerf + (k-1); 5354 const PetscInt oelb = oelf + (k-1); 5355 const PetscInt oerb = oelb + (k-1); 5356 const PetscInt ovblf = oerb + (k-1); 5357 const PetscInt ovblb = ovblf + 1; 5358 const PetscInt ovbrb = ovblb + 1; 5359 const PetscInt ovbrf = ovbrb + 1; 5360 const PetscInt ovtlf = ovbrf + 1; 5361 const PetscInt ovtrf = ovtlf + 1; 5362 const PetscInt ovtrb = ovtrf + 1; 5363 const PetscInt ovtlb = ovtrb + 1; 5364 PetscInt o, n; 5365 5366 /* Bottom Slice */ 5367 /* bottom */ 5368 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5369 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5370 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5371 /* middle */ 5372 for (i = 0; i < k-1; ++i) { 5373 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5374 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;} 5375 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5376 } 5377 /* top */ 5378 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5379 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5380 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5381 5382 /* Middle Slice */ 5383 for (j = 0; j < k-1; ++j) { 5384 /* bottom */ 5385 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5386 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; 5387 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5388 /* middle */ 5389 for (i = 0; i < k-1; ++i) { 5390 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5391 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; 5392 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5393 } 5394 /* top */ 5395 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5396 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; 5397 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5398 } 5399 5400 /* Top Slice */ 5401 /* bottom */ 5402 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5403 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5404 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5405 /* middle */ 5406 for (i = 0; i < k-1; ++i) { 5407 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5408 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5409 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5410 } 5411 /* top */ 5412 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5413 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5414 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5415 5416 foffset = offset; 5417 } 5418 break; 5419 default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5420 } 5421 } 5422 PetscCheckFalse(offset != size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5423 /* Check permutation */ 5424 { 5425 PetscInt *check; 5426 5427 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5428 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]);} 5429 for (i = 0; i < size; ++i) check[perm[i]] = i; 5430 for (i = 0; i < size; ++i) {PetscCheckFalse(check[i] < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5431 ierr = PetscFree(check);CHKERRQ(ierr); 5432 } 5433 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5434 if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5435 PetscInt *loc_perm; 5436 ierr = PetscMalloc1(size*2, &loc_perm);CHKERRQ(ierr); 5437 for (PetscInt i=0; i<size; i++) { 5438 loc_perm[i] = perm[i]; 5439 loc_perm[size+i] = size + perm[i]; 5440 } 5441 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm);CHKERRQ(ierr); 5442 } 5443 } 5444 PetscFunctionReturn(0); 5445 } 5446 5447 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5448 { 5449 PetscDS prob; 5450 PetscInt depth, Nf, h; 5451 DMLabel label; 5452 PetscErrorCode ierr; 5453 5454 PetscFunctionBeginHot; 5455 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5456 Nf = prob->Nf; 5457 label = dm->depthLabel; 5458 *dspace = NULL; 5459 if (field < Nf) { 5460 PetscObject disc = prob->disc[field]; 5461 5462 if (disc->classid == PETSCFE_CLASSID) { 5463 PetscDualSpace dsp; 5464 5465 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5466 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5467 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5468 h = depth - 1 - h; 5469 if (h) { 5470 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5471 } else { 5472 *dspace = dsp; 5473 } 5474 } 5475 } 5476 PetscFunctionReturn(0); 5477 } 5478 5479 static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5480 { 5481 PetscScalar *array, *vArray; 5482 const PetscInt *cone, *coneO; 5483 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5484 PetscErrorCode ierr; 5485 5486 PetscFunctionBeginHot; 5487 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5488 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5489 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5490 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5491 if (!values || !*values) { 5492 if ((point >= pStart) && (point < pEnd)) { 5493 PetscInt dof; 5494 5495 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5496 size += dof; 5497 } 5498 for (p = 0; p < numPoints; ++p) { 5499 const PetscInt cp = cone[p]; 5500 PetscInt dof; 5501 5502 if ((cp < pStart) || (cp >= pEnd)) continue; 5503 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5504 size += dof; 5505 } 5506 if (!values) { 5507 if (csize) *csize = size; 5508 PetscFunctionReturn(0); 5509 } 5510 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5511 } else { 5512 array = *values; 5513 } 5514 size = 0; 5515 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5516 if ((point >= pStart) && (point < pEnd)) { 5517 PetscInt dof, off, d; 5518 PetscScalar *varr; 5519 5520 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5521 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5522 varr = &vArray[off]; 5523 for (d = 0; d < dof; ++d, ++offset) { 5524 array[offset] = varr[d]; 5525 } 5526 size += dof; 5527 } 5528 for (p = 0; p < numPoints; ++p) { 5529 const PetscInt cp = cone[p]; 5530 PetscInt o = coneO[p]; 5531 PetscInt dof, off, d; 5532 PetscScalar *varr; 5533 5534 if ((cp < pStart) || (cp >= pEnd)) continue; 5535 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5536 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5537 varr = &vArray[off]; 5538 if (o >= 0) { 5539 for (d = 0; d < dof; ++d, ++offset) { 5540 array[offset] = varr[d]; 5541 } 5542 } else { 5543 for (d = dof-1; d >= 0; --d, ++offset) { 5544 array[offset] = varr[d]; 5545 } 5546 } 5547 size += dof; 5548 } 5549 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5550 if (!*values) { 5551 if (csize) *csize = size; 5552 *values = array; 5553 } else { 5554 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5555 *csize = size; 5556 } 5557 PetscFunctionReturn(0); 5558 } 5559 5560 /* Compress out points not in the section */ 5561 static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5562 { 5563 const PetscInt np = *numPoints; 5564 PetscInt pStart, pEnd, p, q; 5565 PetscErrorCode ierr; 5566 5567 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5568 for (p = 0, q = 0; p < np; ++p) { 5569 const PetscInt r = points[p*2]; 5570 if ((r >= pStart) && (r < pEnd)) { 5571 points[q*2] = r; 5572 points[q*2+1] = points[p*2+1]; 5573 ++q; 5574 } 5575 } 5576 *numPoints = q; 5577 return 0; 5578 } 5579 5580 /* Compressed closure does not apply closure permutation */ 5581 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5582 { 5583 const PetscInt *cla = NULL; 5584 PetscInt np, *pts = NULL; 5585 PetscErrorCode ierr; 5586 5587 PetscFunctionBeginHot; 5588 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5589 if (*clPoints) { 5590 PetscInt dof, off; 5591 5592 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5593 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5594 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5595 np = dof/2; 5596 pts = (PetscInt *) &cla[off]; 5597 } else { 5598 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5599 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5600 } 5601 *numPoints = np; 5602 *points = pts; 5603 *clp = cla; 5604 PetscFunctionReturn(0); 5605 } 5606 5607 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5608 { 5609 PetscErrorCode ierr; 5610 5611 PetscFunctionBeginHot; 5612 if (!*clPoints) { 5613 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5614 } else { 5615 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5616 } 5617 *numPoints = 0; 5618 *points = NULL; 5619 *clSec = NULL; 5620 *clPoints = NULL; 5621 *clp = NULL; 5622 PetscFunctionReturn(0); 5623 } 5624 5625 static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 5626 { 5627 PetscInt offset = 0, p; 5628 const PetscInt **perms = NULL; 5629 const PetscScalar **flips = NULL; 5630 PetscErrorCode ierr; 5631 5632 PetscFunctionBeginHot; 5633 *size = 0; 5634 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5635 for (p = 0; p < numPoints; p++) { 5636 const PetscInt point = points[2*p]; 5637 const PetscInt *perm = perms ? perms[p] : NULL; 5638 const PetscScalar *flip = flips ? flips[p] : NULL; 5639 PetscInt dof, off, d; 5640 const PetscScalar *varr; 5641 5642 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5643 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5644 varr = &vArray[off]; 5645 if (clperm) { 5646 if (perm) { 5647 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5648 } else { 5649 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5650 } 5651 if (flip) { 5652 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5653 } 5654 } else { 5655 if (perm) { 5656 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5657 } else { 5658 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5659 } 5660 if (flip) { 5661 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5662 } 5663 } 5664 offset += dof; 5665 } 5666 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5667 *size = offset; 5668 PetscFunctionReturn(0); 5669 } 5670 5671 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[]) 5672 { 5673 PetscInt offset = 0, f; 5674 PetscErrorCode ierr; 5675 5676 PetscFunctionBeginHot; 5677 *size = 0; 5678 for (f = 0; f < numFields; ++f) { 5679 PetscInt p; 5680 const PetscInt **perms = NULL; 5681 const PetscScalar **flips = NULL; 5682 5683 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5684 for (p = 0; p < numPoints; p++) { 5685 const PetscInt point = points[2*p]; 5686 PetscInt fdof, foff, b; 5687 const PetscScalar *varr; 5688 const PetscInt *perm = perms ? perms[p] : NULL; 5689 const PetscScalar *flip = flips ? flips[p] : NULL; 5690 5691 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5692 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5693 varr = &vArray[foff]; 5694 if (clperm) { 5695 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5696 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5697 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5698 } else { 5699 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5700 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5701 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5702 } 5703 offset += fdof; 5704 } 5705 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5706 } 5707 *size = offset; 5708 PetscFunctionReturn(0); 5709 } 5710 5711 /*@C 5712 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5713 5714 Not collective 5715 5716 Input Parameters: 5717 + dm - The DM 5718 . section - The section describing the layout in v, or NULL to use the default section 5719 . v - The local vector 5720 - point - The point in the DM 5721 5722 Input/Output Parameters: 5723 + csize - The size of the input values array, or NULL; on output the number of values in the closure 5724 - values - An array to use for the values, or NULL to have it allocated automatically; 5725 if the user provided NULL, it is a borrowed array and should not be freed 5726 5727 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5728 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5729 $ assembly function, and a user may already have allocated storage for this operation. 5730 $ 5731 $ A typical use could be 5732 $ 5733 $ values = NULL; 5734 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5735 $ for (cl = 0; cl < clSize; ++cl) { 5736 $ <Compute on closure> 5737 $ } 5738 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5739 $ 5740 $ or 5741 $ 5742 $ PetscMalloc1(clMaxSize, &values); 5743 $ for (p = pStart; p < pEnd; ++p) { 5744 $ clSize = clMaxSize; 5745 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5746 $ for (cl = 0; cl < clSize; ++cl) { 5747 $ <Compute on closure> 5748 $ } 5749 $ } 5750 $ PetscFree(values); 5751 5752 Fortran Notes: 5753 Since it returns an array, this routine is only available in Fortran 90, and you must 5754 include petsc.h90 in your code. 5755 5756 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5757 5758 Level: intermediate 5759 5760 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5761 @*/ 5762 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5763 { 5764 PetscSection clSection; 5765 IS clPoints; 5766 PetscInt *points = NULL; 5767 const PetscInt *clp, *perm; 5768 PetscInt depth, numFields, numPoints, asize; 5769 PetscErrorCode ierr; 5770 5771 PetscFunctionBeginHot; 5772 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5773 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5774 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5775 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5776 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5777 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5778 if (depth == 1 && numFields < 2) { 5779 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5780 PetscFunctionReturn(0); 5781 } 5782 /* Get points */ 5783 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5784 /* Get sizes */ 5785 asize = 0; 5786 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5787 PetscInt dof; 5788 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5789 asize += dof; 5790 } 5791 if (values) { 5792 const PetscScalar *vArray; 5793 PetscInt size; 5794 5795 if (*values) { 5796 PetscCheckFalse(*csize < asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize); 5797 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5798 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5799 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5800 /* Get values */ 5801 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5802 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5803 PetscCheckFalse(asize != size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5804 /* Cleanup array */ 5805 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5806 } 5807 if (csize) *csize = asize; 5808 /* Cleanup points */ 5809 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5810 PetscFunctionReturn(0); 5811 } 5812 5813 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5814 { 5815 DMLabel depthLabel; 5816 PetscSection clSection; 5817 IS clPoints; 5818 PetscScalar *array; 5819 const PetscScalar *vArray; 5820 PetscInt *points = NULL; 5821 const PetscInt *clp, *perm = NULL; 5822 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5823 PetscErrorCode ierr; 5824 5825 PetscFunctionBeginHot; 5826 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5827 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5828 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5829 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5830 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5831 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5832 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5833 if (mdepth == 1 && numFields < 2) { 5834 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5835 PetscFunctionReturn(0); 5836 } 5837 /* Get points */ 5838 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5839 for (clsize=0,p=0; p<Np; p++) { 5840 PetscInt dof; 5841 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5842 clsize += dof; 5843 } 5844 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5845 /* Filter points */ 5846 for (p = 0; p < numPoints*2; p += 2) { 5847 PetscInt dep; 5848 5849 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5850 if (dep != depth) continue; 5851 points[Np*2+0] = points[p]; 5852 points[Np*2+1] = points[p+1]; 5853 ++Np; 5854 } 5855 /* Get array */ 5856 if (!values || !*values) { 5857 PetscInt asize = 0, dof; 5858 5859 for (p = 0; p < Np*2; p += 2) { 5860 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5861 asize += dof; 5862 } 5863 if (!values) { 5864 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5865 if (csize) *csize = asize; 5866 PetscFunctionReturn(0); 5867 } 5868 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5869 } else { 5870 array = *values; 5871 } 5872 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5873 /* Get values */ 5874 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5875 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5876 /* Cleanup points */ 5877 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5878 /* Cleanup array */ 5879 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5880 if (!*values) { 5881 if (csize) *csize = size; 5882 *values = array; 5883 } else { 5884 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5885 *csize = size; 5886 } 5887 PetscFunctionReturn(0); 5888 } 5889 5890 /*@C 5891 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5892 5893 Not collective 5894 5895 Input Parameters: 5896 + dm - The DM 5897 . section - The section describing the layout in v, or NULL to use the default section 5898 . v - The local vector 5899 . point - The point in the DM 5900 . csize - The number of values in the closure, or NULL 5901 - values - The array of values, which is a borrowed array and should not be freed 5902 5903 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5904 5905 Fortran Notes: 5906 Since it returns an array, this routine is only available in Fortran 90, and you must 5907 include petsc.h90 in your code. 5908 5909 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5910 5911 Level: intermediate 5912 5913 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5914 @*/ 5915 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5916 { 5917 PetscInt size = 0; 5918 PetscErrorCode ierr; 5919 5920 PetscFunctionBegin; 5921 /* Should work without recalculating size */ 5922 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5923 *values = NULL; 5924 PetscFunctionReturn(0); 5925 } 5926 5927 static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 5928 static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5929 5930 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[]) 5931 { 5932 PetscInt cdof; /* The number of constraints on this point */ 5933 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5934 PetscScalar *a; 5935 PetscInt off, cind = 0, k; 5936 PetscErrorCode ierr; 5937 5938 PetscFunctionBegin; 5939 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5940 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5941 a = &array[off]; 5942 if (!cdof || setBC) { 5943 if (clperm) { 5944 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5945 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5946 } else { 5947 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5948 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5949 } 5950 } else { 5951 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5952 if (clperm) { 5953 if (perm) {for (k = 0; k < dof; ++k) { 5954 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5955 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5956 } 5957 } else { 5958 for (k = 0; k < dof; ++k) { 5959 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5960 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5961 } 5962 } 5963 } else { 5964 if (perm) { 5965 for (k = 0; k < dof; ++k) { 5966 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5967 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5968 } 5969 } else { 5970 for (k = 0; k < dof; ++k) { 5971 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5972 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5973 } 5974 } 5975 } 5976 } 5977 PetscFunctionReturn(0); 5978 } 5979 5980 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[]) 5981 { 5982 PetscInt cdof; /* The number of constraints on this point */ 5983 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5984 PetscScalar *a; 5985 PetscInt off, cind = 0, k; 5986 PetscErrorCode ierr; 5987 5988 PetscFunctionBegin; 5989 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5990 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5991 a = &array[off]; 5992 if (cdof) { 5993 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5994 if (clperm) { 5995 if (perm) { 5996 for (k = 0; k < dof; ++k) { 5997 if ((cind < cdof) && (k == cdofs[cind])) { 5998 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5999 cind++; 6000 } 6001 } 6002 } else { 6003 for (k = 0; k < dof; ++k) { 6004 if ((cind < cdof) && (k == cdofs[cind])) { 6005 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 6006 cind++; 6007 } 6008 } 6009 } 6010 } else { 6011 if (perm) { 6012 for (k = 0; k < dof; ++k) { 6013 if ((cind < cdof) && (k == cdofs[cind])) { 6014 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 6015 cind++; 6016 } 6017 } 6018 } else { 6019 for (k = 0; k < dof; ++k) { 6020 if ((cind < cdof) && (k == cdofs[cind])) { 6021 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 6022 cind++; 6023 } 6024 } 6025 } 6026 } 6027 } 6028 PetscFunctionReturn(0); 6029 } 6030 6031 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[]) 6032 { 6033 PetscScalar *a; 6034 PetscInt fdof, foff, fcdof, foffset = *offset; 6035 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6036 PetscInt cind = 0, b; 6037 PetscErrorCode ierr; 6038 6039 PetscFunctionBegin; 6040 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6041 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6042 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6043 a = &array[foff]; 6044 if (!fcdof || setBC) { 6045 if (clperm) { 6046 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 6047 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6048 } else { 6049 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 6050 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6051 } 6052 } else { 6053 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6054 if (clperm) { 6055 if (perm) { 6056 for (b = 0; b < fdof; b++) { 6057 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6058 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6059 } 6060 } else { 6061 for (b = 0; b < fdof; b++) { 6062 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6063 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6064 } 6065 } 6066 } else { 6067 if (perm) { 6068 for (b = 0; b < fdof; b++) { 6069 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6070 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6071 } 6072 } else { 6073 for (b = 0; b < fdof; b++) { 6074 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6075 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6076 } 6077 } 6078 } 6079 } 6080 *offset += fdof; 6081 PetscFunctionReturn(0); 6082 } 6083 6084 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[]) 6085 { 6086 PetscScalar *a; 6087 PetscInt fdof, foff, fcdof, foffset = *offset; 6088 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6089 PetscInt Nc, cind = 0, ncind = 0, b; 6090 PetscBool ncSet, fcSet; 6091 PetscErrorCode ierr; 6092 6093 PetscFunctionBegin; 6094 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 6095 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6096 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6097 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6098 a = &array[foff]; 6099 if (fcdof) { 6100 /* We just override fcdof and fcdofs with Ncc and comps */ 6101 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6102 if (clperm) { 6103 if (perm) { 6104 if (comps) { 6105 for (b = 0; b < fdof; b++) { 6106 ncSet = fcSet = PETSC_FALSE; 6107 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6108 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6109 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6110 } 6111 } else { 6112 for (b = 0; b < fdof; b++) { 6113 if ((cind < fcdof) && (b == fcdofs[cind])) { 6114 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6115 ++cind; 6116 } 6117 } 6118 } 6119 } else { 6120 if (comps) { 6121 for (b = 0; b < fdof; b++) { 6122 ncSet = fcSet = PETSC_FALSE; 6123 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6124 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6125 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6126 } 6127 } else { 6128 for (b = 0; b < fdof; b++) { 6129 if ((cind < fcdof) && (b == fcdofs[cind])) { 6130 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6131 ++cind; 6132 } 6133 } 6134 } 6135 } 6136 } else { 6137 if (perm) { 6138 if (comps) { 6139 for (b = 0; b < fdof; b++) { 6140 ncSet = fcSet = PETSC_FALSE; 6141 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6142 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6143 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6144 } 6145 } else { 6146 for (b = 0; b < fdof; b++) { 6147 if ((cind < fcdof) && (b == fcdofs[cind])) { 6148 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6149 ++cind; 6150 } 6151 } 6152 } 6153 } else { 6154 if (comps) { 6155 for (b = 0; b < fdof; b++) { 6156 ncSet = fcSet = PETSC_FALSE; 6157 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6158 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6159 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6160 } 6161 } else { 6162 for (b = 0; b < fdof; b++) { 6163 if ((cind < fcdof) && (b == fcdofs[cind])) { 6164 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6165 ++cind; 6166 } 6167 } 6168 } 6169 } 6170 } 6171 } 6172 *offset += fdof; 6173 PetscFunctionReturn(0); 6174 } 6175 6176 static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6177 { 6178 PetscScalar *array; 6179 const PetscInt *cone, *coneO; 6180 PetscInt pStart, pEnd, p, numPoints, off, dof; 6181 PetscErrorCode ierr; 6182 6183 PetscFunctionBeginHot; 6184 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6185 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6186 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6187 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6188 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6189 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6190 const PetscInt cp = !p ? point : cone[p-1]; 6191 const PetscInt o = !p ? 0 : coneO[p-1]; 6192 6193 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 6194 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6195 /* ADD_VALUES */ 6196 { 6197 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6198 PetscScalar *a; 6199 PetscInt cdof, coff, cind = 0, k; 6200 6201 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 6202 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 6203 a = &array[coff]; 6204 if (!cdof) { 6205 if (o >= 0) { 6206 for (k = 0; k < dof; ++k) { 6207 a[k] += values[off+k]; 6208 } 6209 } else { 6210 for (k = 0; k < dof; ++k) { 6211 a[k] += values[off+dof-k-1]; 6212 } 6213 } 6214 } else { 6215 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6216 if (o >= 0) { 6217 for (k = 0; k < dof; ++k) { 6218 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6219 a[k] += values[off+k]; 6220 } 6221 } else { 6222 for (k = 0; k < dof; ++k) { 6223 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6224 a[k] += values[off+dof-k-1]; 6225 } 6226 } 6227 } 6228 } 6229 } 6230 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6231 PetscFunctionReturn(0); 6232 } 6233 6234 /*@C 6235 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6236 6237 Not collective 6238 6239 Input Parameters: 6240 + dm - The DM 6241 . section - The section describing the layout in v, or NULL to use the default section 6242 . v - The local vector 6243 . point - The point in the DM 6244 . values - The array of values 6245 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6246 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6247 6248 Fortran Notes: 6249 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6250 6251 Level: intermediate 6252 6253 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6254 @*/ 6255 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6256 { 6257 PetscSection clSection; 6258 IS clPoints; 6259 PetscScalar *array; 6260 PetscInt *points = NULL; 6261 const PetscInt *clp, *clperm = NULL; 6262 PetscInt depth, numFields, numPoints, p, clsize; 6263 PetscErrorCode ierr; 6264 6265 PetscFunctionBeginHot; 6266 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6267 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6268 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6269 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6270 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6271 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6272 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6273 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6274 PetscFunctionReturn(0); 6275 } 6276 /* Get points */ 6277 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6278 for (clsize=0,p=0; p<numPoints; p++) { 6279 PetscInt dof; 6280 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6281 clsize += dof; 6282 } 6283 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6284 /* Get array */ 6285 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6286 /* Get values */ 6287 if (numFields > 0) { 6288 PetscInt offset = 0, f; 6289 for (f = 0; f < numFields; ++f) { 6290 const PetscInt **perms = NULL; 6291 const PetscScalar **flips = NULL; 6292 6293 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6294 switch (mode) { 6295 case INSERT_VALUES: 6296 for (p = 0; p < numPoints; p++) { 6297 const PetscInt point = points[2*p]; 6298 const PetscInt *perm = perms ? perms[p] : NULL; 6299 const PetscScalar *flip = flips ? flips[p] : NULL; 6300 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6301 } break; 6302 case INSERT_ALL_VALUES: 6303 for (p = 0; p < numPoints; p++) { 6304 const PetscInt point = points[2*p]; 6305 const PetscInt *perm = perms ? perms[p] : NULL; 6306 const PetscScalar *flip = flips ? flips[p] : NULL; 6307 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6308 } break; 6309 case INSERT_BC_VALUES: 6310 for (p = 0; p < numPoints; p++) { 6311 const PetscInt point = points[2*p]; 6312 const PetscInt *perm = perms ? perms[p] : NULL; 6313 const PetscScalar *flip = flips ? flips[p] : NULL; 6314 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6315 } break; 6316 case ADD_VALUES: 6317 for (p = 0; p < numPoints; p++) { 6318 const PetscInt point = points[2*p]; 6319 const PetscInt *perm = perms ? perms[p] : NULL; 6320 const PetscScalar *flip = flips ? flips[p] : NULL; 6321 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6322 } break; 6323 case ADD_ALL_VALUES: 6324 for (p = 0; p < numPoints; p++) { 6325 const PetscInt point = points[2*p]; 6326 const PetscInt *perm = perms ? perms[p] : NULL; 6327 const PetscScalar *flip = flips ? flips[p] : NULL; 6328 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6329 } break; 6330 case ADD_BC_VALUES: 6331 for (p = 0; p < numPoints; p++) { 6332 const PetscInt point = points[2*p]; 6333 const PetscInt *perm = perms ? perms[p] : NULL; 6334 const PetscScalar *flip = flips ? flips[p] : NULL; 6335 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6336 } break; 6337 default: 6338 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6339 } 6340 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6341 } 6342 } else { 6343 PetscInt dof, off; 6344 const PetscInt **perms = NULL; 6345 const PetscScalar **flips = NULL; 6346 6347 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6348 switch (mode) { 6349 case INSERT_VALUES: 6350 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6351 const PetscInt point = points[2*p]; 6352 const PetscInt *perm = perms ? perms[p] : NULL; 6353 const PetscScalar *flip = flips ? flips[p] : NULL; 6354 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6355 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6356 } break; 6357 case INSERT_ALL_VALUES: 6358 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6359 const PetscInt point = points[2*p]; 6360 const PetscInt *perm = perms ? perms[p] : NULL; 6361 const PetscScalar *flip = flips ? flips[p] : NULL; 6362 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6363 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6364 } break; 6365 case INSERT_BC_VALUES: 6366 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6367 const PetscInt point = points[2*p]; 6368 const PetscInt *perm = perms ? perms[p] : NULL; 6369 const PetscScalar *flip = flips ? flips[p] : NULL; 6370 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6371 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6372 } break; 6373 case ADD_VALUES: 6374 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6375 const PetscInt point = points[2*p]; 6376 const PetscInt *perm = perms ? perms[p] : NULL; 6377 const PetscScalar *flip = flips ? flips[p] : NULL; 6378 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6379 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6380 } break; 6381 case ADD_ALL_VALUES: 6382 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6383 const PetscInt point = points[2*p]; 6384 const PetscInt *perm = perms ? perms[p] : NULL; 6385 const PetscScalar *flip = flips ? flips[p] : NULL; 6386 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6387 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6388 } break; 6389 case ADD_BC_VALUES: 6390 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6391 const PetscInt point = points[2*p]; 6392 const PetscInt *perm = perms ? perms[p] : NULL; 6393 const PetscScalar *flip = flips ? flips[p] : NULL; 6394 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6395 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6396 } break; 6397 default: 6398 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6399 } 6400 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6401 } 6402 /* Cleanup points */ 6403 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6404 /* Cleanup array */ 6405 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6406 PetscFunctionReturn(0); 6407 } 6408 6409 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6410 static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6411 { 6412 PetscFunctionBegin; 6413 if (label) { 6414 PetscInt val, fdof; 6415 PetscErrorCode ierr; 6416 6417 /* There is a problem with this: 6418 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6419 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6420 Thus I am only going to check val != -1, not val != labelId 6421 */ 6422 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6423 if (val < 0) { 6424 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6425 *offset += fdof; 6426 PetscFunctionReturn(1); 6427 } 6428 } 6429 PetscFunctionReturn(0); 6430 } 6431 6432 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6433 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) 6434 { 6435 PetscSection clSection; 6436 IS clPoints; 6437 PetscScalar *array; 6438 PetscInt *points = NULL; 6439 const PetscInt *clp; 6440 PetscInt numFields, numPoints, p; 6441 PetscInt offset = 0, f; 6442 PetscErrorCode ierr; 6443 6444 PetscFunctionBeginHot; 6445 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6446 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6447 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6448 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6449 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6450 /* Get points */ 6451 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6452 /* Get array */ 6453 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6454 /* Get values */ 6455 for (f = 0; f < numFields; ++f) { 6456 const PetscInt **perms = NULL; 6457 const PetscScalar **flips = NULL; 6458 6459 if (!fieldActive[f]) { 6460 for (p = 0; p < numPoints*2; p += 2) { 6461 PetscInt fdof; 6462 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6463 offset += fdof; 6464 } 6465 continue; 6466 } 6467 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6468 switch (mode) { 6469 case INSERT_VALUES: 6470 for (p = 0; p < numPoints; p++) { 6471 const PetscInt point = points[2*p]; 6472 const PetscInt *perm = perms ? perms[p] : NULL; 6473 const PetscScalar *flip = flips ? flips[p] : NULL; 6474 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6475 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6476 } break; 6477 case INSERT_ALL_VALUES: 6478 for (p = 0; p < numPoints; p++) { 6479 const PetscInt point = points[2*p]; 6480 const PetscInt *perm = perms ? perms[p] : NULL; 6481 const PetscScalar *flip = flips ? flips[p] : NULL; 6482 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6483 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6484 } break; 6485 case INSERT_BC_VALUES: 6486 for (p = 0; p < numPoints; p++) { 6487 const PetscInt point = points[2*p]; 6488 const PetscInt *perm = perms ? perms[p] : NULL; 6489 const PetscScalar *flip = flips ? flips[p] : NULL; 6490 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6491 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6492 } break; 6493 case ADD_VALUES: 6494 for (p = 0; p < numPoints; p++) { 6495 const PetscInt point = points[2*p]; 6496 const PetscInt *perm = perms ? perms[p] : NULL; 6497 const PetscScalar *flip = flips ? flips[p] : NULL; 6498 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6499 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6500 } break; 6501 case ADD_ALL_VALUES: 6502 for (p = 0; p < numPoints; p++) { 6503 const PetscInt point = points[2*p]; 6504 const PetscInt *perm = perms ? perms[p] : NULL; 6505 const PetscScalar *flip = flips ? flips[p] : NULL; 6506 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6507 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6508 } break; 6509 default: 6510 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6511 } 6512 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6513 } 6514 /* Cleanup points */ 6515 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6516 /* Cleanup array */ 6517 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6518 PetscFunctionReturn(0); 6519 } 6520 6521 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6522 { 6523 PetscMPIInt rank; 6524 PetscInt i, j; 6525 PetscErrorCode ierr; 6526 6527 PetscFunctionBegin; 6528 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6529 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6530 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6531 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6532 numCIndices = numCIndices ? numCIndices : numRIndices; 6533 if (!values) PetscFunctionReturn(0); 6534 for (i = 0; i < numRIndices; i++) { 6535 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6536 for (j = 0; j < numCIndices; j++) { 6537 #if defined(PETSC_USE_COMPLEX) 6538 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6539 #else 6540 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6541 #endif 6542 } 6543 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6544 } 6545 PetscFunctionReturn(0); 6546 } 6547 6548 /* 6549 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6550 6551 Input Parameters: 6552 + section - The section for this data layout 6553 . islocal - Is the section (and thus indices being requested) local or global? 6554 . point - The point contributing dofs with these indices 6555 . off - The global offset of this point 6556 . loff - The local offset of each field 6557 . setBC - The flag determining whether to include indices of boundary values 6558 . perm - A permutation of the dofs on this point, or NULL 6559 - indperm - A permutation of the entire indices array, or NULL 6560 6561 Output Parameter: 6562 . indices - Indices for dofs on this point 6563 6564 Level: developer 6565 6566 Note: The indices could be local or global, depending on the value of 'off'. 6567 */ 6568 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6569 { 6570 PetscInt dof; /* The number of unknowns on this point */ 6571 PetscInt cdof; /* The number of constraints on this point */ 6572 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6573 PetscInt cind = 0, k; 6574 PetscErrorCode ierr; 6575 6576 PetscFunctionBegin; 6577 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6578 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6579 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6580 if (!cdof || setBC) { 6581 for (k = 0; k < dof; ++k) { 6582 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6583 const PetscInt ind = indperm ? indperm[preind] : preind; 6584 6585 indices[ind] = off + k; 6586 } 6587 } else { 6588 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6589 for (k = 0; k < dof; ++k) { 6590 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6591 const PetscInt ind = indperm ? indperm[preind] : preind; 6592 6593 if ((cind < cdof) && (k == cdofs[cind])) { 6594 /* Insert check for returning constrained indices */ 6595 indices[ind] = -(off+k+1); 6596 ++cind; 6597 } else { 6598 indices[ind] = off + k - (islocal ? 0 : cind); 6599 } 6600 } 6601 } 6602 *loff += dof; 6603 PetscFunctionReturn(0); 6604 } 6605 6606 /* 6607 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6608 6609 Input Parameters: 6610 + section - a section (global or local) 6611 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6612 . point - point within section 6613 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6614 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6615 . setBC - identify constrained (boundary condition) points via involution. 6616 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6617 . permsoff - offset 6618 - indperm - index permutation 6619 6620 Output Parameter: 6621 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6622 . indices - array to hold indices (as defined by section) of each dof associated with point 6623 6624 Notes: 6625 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6626 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6627 in the local vector. 6628 6629 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6630 significant). It is invalid to call with a global section and setBC=true. 6631 6632 Developer Note: 6633 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6634 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6635 offset could be obtained from the section instead of passing it explicitly as we do now. 6636 6637 Example: 6638 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6639 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6640 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6641 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. 6642 6643 Level: developer 6644 */ 6645 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[]) 6646 { 6647 PetscInt numFields, foff, f; 6648 PetscErrorCode ierr; 6649 6650 PetscFunctionBegin; 6651 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6652 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6653 for (f = 0, foff = 0; f < numFields; ++f) { 6654 PetscInt fdof, cfdof; 6655 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6656 PetscInt cind = 0, b; 6657 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6658 6659 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6660 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6661 if (!cfdof || setBC) { 6662 for (b = 0; b < fdof; ++b) { 6663 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6664 const PetscInt ind = indperm ? indperm[preind] : preind; 6665 6666 indices[ind] = off+foff+b; 6667 } 6668 } else { 6669 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6670 for (b = 0; b < fdof; ++b) { 6671 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6672 const PetscInt ind = indperm ? indperm[preind] : preind; 6673 6674 if ((cind < cfdof) && (b == fcdofs[cind])) { 6675 indices[ind] = -(off+foff+b+1); 6676 ++cind; 6677 } else { 6678 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6679 } 6680 } 6681 } 6682 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6683 foffs[f] += fdof; 6684 } 6685 PetscFunctionReturn(0); 6686 } 6687 6688 /* 6689 This version believes the globalSection offsets for each field, rather than just the point offset 6690 6691 . foffs - The offset into 'indices' for each field, since it is segregated by field 6692 6693 Notes: 6694 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6695 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6696 */ 6697 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6698 { 6699 PetscInt numFields, foff, f; 6700 PetscErrorCode ierr; 6701 6702 PetscFunctionBegin; 6703 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6704 for (f = 0; f < numFields; ++f) { 6705 PetscInt fdof, cfdof; 6706 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6707 PetscInt cind = 0, b; 6708 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6709 6710 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6711 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6712 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6713 if (!cfdof) { 6714 for (b = 0; b < fdof; ++b) { 6715 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6716 const PetscInt ind = indperm ? indperm[preind] : preind; 6717 6718 indices[ind] = foff+b; 6719 } 6720 } else { 6721 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6722 for (b = 0; b < fdof; ++b) { 6723 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6724 const PetscInt ind = indperm ? indperm[preind] : preind; 6725 6726 if ((cind < cfdof) && (b == fcdofs[cind])) { 6727 indices[ind] = -(foff+b+1); 6728 ++cind; 6729 } else { 6730 indices[ind] = foff+b-cind; 6731 } 6732 } 6733 } 6734 foffs[f] += fdof; 6735 } 6736 PetscFunctionReturn(0); 6737 } 6738 6739 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) 6740 { 6741 Mat cMat; 6742 PetscSection aSec, cSec; 6743 IS aIS; 6744 PetscInt aStart = -1, aEnd = -1; 6745 const PetscInt *anchors; 6746 PetscInt numFields, f, p, q, newP = 0; 6747 PetscInt newNumPoints = 0, newNumIndices = 0; 6748 PetscInt *newPoints, *indices, *newIndices; 6749 PetscInt maxAnchor, maxDof; 6750 PetscInt newOffsets[32]; 6751 PetscInt *pointMatOffsets[32]; 6752 PetscInt *newPointOffsets[32]; 6753 PetscScalar *pointMat[32]; 6754 PetscScalar *newValues=NULL,*tmpValues; 6755 PetscBool anyConstrained = PETSC_FALSE; 6756 PetscErrorCode ierr; 6757 6758 PetscFunctionBegin; 6759 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6760 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6761 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6762 6763 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6764 /* if there are point-to-point constraints */ 6765 if (aSec) { 6766 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6767 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6768 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6769 /* figure out how many points are going to be in the new element matrix 6770 * (we allow double counting, because it's all just going to be summed 6771 * into the global matrix anyway) */ 6772 for (p = 0; p < 2*numPoints; p+=2) { 6773 PetscInt b = points[p]; 6774 PetscInt bDof = 0, bSecDof; 6775 6776 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6777 if (!bSecDof) { 6778 continue; 6779 } 6780 if (b >= aStart && b < aEnd) { 6781 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6782 } 6783 if (bDof) { 6784 /* this point is constrained */ 6785 /* it is going to be replaced by its anchors */ 6786 PetscInt bOff, q; 6787 6788 anyConstrained = PETSC_TRUE; 6789 newNumPoints += bDof; 6790 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6791 for (q = 0; q < bDof; q++) { 6792 PetscInt a = anchors[bOff + q]; 6793 PetscInt aDof; 6794 6795 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6796 newNumIndices += aDof; 6797 for (f = 0; f < numFields; ++f) { 6798 PetscInt fDof; 6799 6800 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6801 newOffsets[f+1] += fDof; 6802 } 6803 } 6804 } 6805 else { 6806 /* this point is not constrained */ 6807 newNumPoints++; 6808 newNumIndices += bSecDof; 6809 for (f = 0; f < numFields; ++f) { 6810 PetscInt fDof; 6811 6812 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6813 newOffsets[f+1] += fDof; 6814 } 6815 } 6816 } 6817 } 6818 if (!anyConstrained) { 6819 if (outNumPoints) *outNumPoints = 0; 6820 if (outNumIndices) *outNumIndices = 0; 6821 if (outPoints) *outPoints = NULL; 6822 if (outValues) *outValues = NULL; 6823 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6824 PetscFunctionReturn(0); 6825 } 6826 6827 if (outNumPoints) *outNumPoints = newNumPoints; 6828 if (outNumIndices) *outNumIndices = newNumIndices; 6829 6830 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6831 6832 if (!outPoints && !outValues) { 6833 if (offsets) { 6834 for (f = 0; f <= numFields; f++) { 6835 offsets[f] = newOffsets[f]; 6836 } 6837 } 6838 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6839 PetscFunctionReturn(0); 6840 } 6841 6842 PetscCheckFalse(numFields && newOffsets[numFields] != newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6843 6844 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat, NULL);CHKERRQ(ierr); 6845 6846 /* workspaces */ 6847 if (numFields) { 6848 for (f = 0; f < numFields; f++) { 6849 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6850 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6851 } 6852 } 6853 else { 6854 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6855 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6856 } 6857 6858 /* get workspaces for the point-to-point matrices */ 6859 if (numFields) { 6860 PetscInt totalOffset, totalMatOffset; 6861 6862 for (p = 0; p < numPoints; p++) { 6863 PetscInt b = points[2*p]; 6864 PetscInt bDof = 0, bSecDof; 6865 6866 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6867 if (!bSecDof) { 6868 for (f = 0; f < numFields; f++) { 6869 newPointOffsets[f][p + 1] = 0; 6870 pointMatOffsets[f][p + 1] = 0; 6871 } 6872 continue; 6873 } 6874 if (b >= aStart && b < aEnd) { 6875 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6876 } 6877 if (bDof) { 6878 for (f = 0; f < numFields; f++) { 6879 PetscInt fDof, q, bOff, allFDof = 0; 6880 6881 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6882 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6883 for (q = 0; q < bDof; q++) { 6884 PetscInt a = anchors[bOff + q]; 6885 PetscInt aFDof; 6886 6887 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6888 allFDof += aFDof; 6889 } 6890 newPointOffsets[f][p+1] = allFDof; 6891 pointMatOffsets[f][p+1] = fDof * allFDof; 6892 } 6893 } 6894 else { 6895 for (f = 0; f < numFields; f++) { 6896 PetscInt fDof; 6897 6898 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6899 newPointOffsets[f][p+1] = fDof; 6900 pointMatOffsets[f][p+1] = 0; 6901 } 6902 } 6903 } 6904 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6905 newPointOffsets[f][0] = totalOffset; 6906 pointMatOffsets[f][0] = totalMatOffset; 6907 for (p = 0; p < numPoints; p++) { 6908 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6909 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6910 } 6911 totalOffset = newPointOffsets[f][numPoints]; 6912 totalMatOffset = pointMatOffsets[f][numPoints]; 6913 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6914 } 6915 } 6916 else { 6917 for (p = 0; p < numPoints; p++) { 6918 PetscInt b = points[2*p]; 6919 PetscInt bDof = 0, bSecDof; 6920 6921 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6922 if (!bSecDof) { 6923 newPointOffsets[0][p + 1] = 0; 6924 pointMatOffsets[0][p + 1] = 0; 6925 continue; 6926 } 6927 if (b >= aStart && b < aEnd) { 6928 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6929 } 6930 if (bDof) { 6931 PetscInt bOff, q, allDof = 0; 6932 6933 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6934 for (q = 0; q < bDof; q++) { 6935 PetscInt a = anchors[bOff + q], aDof; 6936 6937 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6938 allDof += aDof; 6939 } 6940 newPointOffsets[0][p+1] = allDof; 6941 pointMatOffsets[0][p+1] = bSecDof * allDof; 6942 } 6943 else { 6944 newPointOffsets[0][p+1] = bSecDof; 6945 pointMatOffsets[0][p+1] = 0; 6946 } 6947 } 6948 newPointOffsets[0][0] = 0; 6949 pointMatOffsets[0][0] = 0; 6950 for (p = 0; p < numPoints; p++) { 6951 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6952 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6953 } 6954 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6955 } 6956 6957 /* output arrays */ 6958 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6959 6960 /* get the point-to-point matrices; construct newPoints */ 6961 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6962 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6963 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6964 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6965 if (numFields) { 6966 for (p = 0, newP = 0; p < numPoints; p++) { 6967 PetscInt b = points[2*p]; 6968 PetscInt o = points[2*p+1]; 6969 PetscInt bDof = 0, bSecDof; 6970 6971 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6972 if (!bSecDof) { 6973 continue; 6974 } 6975 if (b >= aStart && b < aEnd) { 6976 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6977 } 6978 if (bDof) { 6979 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6980 6981 fStart[0] = 0; 6982 fEnd[0] = 0; 6983 for (f = 0; f < numFields; f++) { 6984 PetscInt fDof; 6985 6986 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6987 fStart[f+1] = fStart[f] + fDof; 6988 fEnd[f+1] = fStart[f+1]; 6989 } 6990 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6991 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6992 6993 fAnchorStart[0] = 0; 6994 fAnchorEnd[0] = 0; 6995 for (f = 0; f < numFields; f++) { 6996 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6997 6998 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6999 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 7000 } 7001 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 7002 for (q = 0; q < bDof; q++) { 7003 PetscInt a = anchors[bOff + q], aOff; 7004 7005 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7006 newPoints[2*(newP + q)] = a; 7007 newPoints[2*(newP + q) + 1] = 0; 7008 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7009 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 7010 } 7011 newP += bDof; 7012 7013 if (outValues) { 7014 /* get the point-to-point submatrix */ 7015 for (f = 0; f < numFields; f++) { 7016 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 7017 } 7018 } 7019 } 7020 else { 7021 newPoints[2 * newP] = b; 7022 newPoints[2 * newP + 1] = o; 7023 newP++; 7024 } 7025 } 7026 } else { 7027 for (p = 0; p < numPoints; p++) { 7028 PetscInt b = points[2*p]; 7029 PetscInt o = points[2*p+1]; 7030 PetscInt bDof = 0, bSecDof; 7031 7032 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 7033 if (!bSecDof) { 7034 continue; 7035 } 7036 if (b >= aStart && b < aEnd) { 7037 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 7038 } 7039 if (bDof) { 7040 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7041 7042 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 7043 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 7044 7045 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 7046 for (q = 0; q < bDof; q++) { 7047 PetscInt a = anchors[bOff + q], aOff; 7048 7049 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7050 7051 newPoints[2*(newP + q)] = a; 7052 newPoints[2*(newP + q) + 1] = 0; 7053 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7054 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 7055 } 7056 newP += bDof; 7057 7058 /* get the point-to-point submatrix */ 7059 if (outValues) { 7060 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 7061 } 7062 } 7063 else { 7064 newPoints[2 * newP] = b; 7065 newPoints[2 * newP + 1] = o; 7066 newP++; 7067 } 7068 } 7069 } 7070 7071 if (outValues) { 7072 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7073 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 7074 /* multiply constraints on the right */ 7075 if (numFields) { 7076 for (f = 0; f < numFields; f++) { 7077 PetscInt oldOff = offsets[f]; 7078 7079 for (p = 0; p < numPoints; p++) { 7080 PetscInt cStart = newPointOffsets[f][p]; 7081 PetscInt b = points[2 * p]; 7082 PetscInt c, r, k; 7083 PetscInt dof; 7084 7085 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7086 if (!dof) { 7087 continue; 7088 } 7089 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7090 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7091 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7092 7093 for (r = 0; r < numIndices; r++) { 7094 for (c = 0; c < nCols; c++) { 7095 for (k = 0; k < dof; k++) { 7096 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7097 } 7098 } 7099 } 7100 } 7101 else { 7102 /* copy this column as is */ 7103 for (r = 0; r < numIndices; r++) { 7104 for (c = 0; c < dof; c++) { 7105 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7106 } 7107 } 7108 } 7109 oldOff += dof; 7110 } 7111 } 7112 } 7113 else { 7114 PetscInt oldOff = 0; 7115 for (p = 0; p < numPoints; p++) { 7116 PetscInt cStart = newPointOffsets[0][p]; 7117 PetscInt b = points[2 * p]; 7118 PetscInt c, r, k; 7119 PetscInt dof; 7120 7121 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7122 if (!dof) { 7123 continue; 7124 } 7125 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7126 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7127 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7128 7129 for (r = 0; r < numIndices; r++) { 7130 for (c = 0; c < nCols; c++) { 7131 for (k = 0; k < dof; k++) { 7132 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7133 } 7134 } 7135 } 7136 } 7137 else { 7138 /* copy this column as is */ 7139 for (r = 0; r < numIndices; r++) { 7140 for (c = 0; c < dof; c++) { 7141 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7142 } 7143 } 7144 } 7145 oldOff += dof; 7146 } 7147 } 7148 7149 if (multiplyLeft) { 7150 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 7151 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 7152 /* multiply constraints transpose on the left */ 7153 if (numFields) { 7154 for (f = 0; f < numFields; f++) { 7155 PetscInt oldOff = offsets[f]; 7156 7157 for (p = 0; p < numPoints; p++) { 7158 PetscInt rStart = newPointOffsets[f][p]; 7159 PetscInt b = points[2 * p]; 7160 PetscInt c, r, k; 7161 PetscInt dof; 7162 7163 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7164 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7165 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7166 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7167 7168 for (r = 0; r < nRows; r++) { 7169 for (c = 0; c < newNumIndices; c++) { 7170 for (k = 0; k < dof; k++) { 7171 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7172 } 7173 } 7174 } 7175 } 7176 else { 7177 /* copy this row as is */ 7178 for (r = 0; r < dof; r++) { 7179 for (c = 0; c < newNumIndices; c++) { 7180 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7181 } 7182 } 7183 } 7184 oldOff += dof; 7185 } 7186 } 7187 } 7188 else { 7189 PetscInt oldOff = 0; 7190 7191 for (p = 0; p < numPoints; p++) { 7192 PetscInt rStart = newPointOffsets[0][p]; 7193 PetscInt b = points[2 * p]; 7194 PetscInt c, r, k; 7195 PetscInt dof; 7196 7197 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7198 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7199 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7200 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7201 7202 for (r = 0; r < nRows; r++) { 7203 for (c = 0; c < newNumIndices; c++) { 7204 for (k = 0; k < dof; k++) { 7205 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7206 } 7207 } 7208 } 7209 } 7210 else { 7211 /* copy this row as is */ 7212 for (r = 0; r < dof; r++) { 7213 for (c = 0; c < newNumIndices; c++) { 7214 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7215 } 7216 } 7217 } 7218 oldOff += dof; 7219 } 7220 } 7221 7222 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7223 } 7224 else { 7225 newValues = tmpValues; 7226 } 7227 } 7228 7229 /* clean up */ 7230 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7231 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7232 7233 if (numFields) { 7234 for (f = 0; f < numFields; f++) { 7235 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7236 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7237 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7238 } 7239 } 7240 else { 7241 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7242 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7243 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7244 } 7245 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7246 7247 /* output */ 7248 if (outPoints) { 7249 *outPoints = newPoints; 7250 } 7251 else { 7252 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7253 } 7254 if (outValues) { 7255 *outValues = newValues; 7256 } 7257 for (f = 0; f <= numFields; f++) { 7258 offsets[f] = newOffsets[f]; 7259 } 7260 PetscFunctionReturn(0); 7261 } 7262 7263 /*@C 7264 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7265 7266 Not collective 7267 7268 Input Parameters: 7269 + dm - The DM 7270 . section - The PetscSection describing the points (a local section) 7271 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7272 . point - The point defining the closure 7273 - useClPerm - Use the closure point permutation if available 7274 7275 Output Parameters: 7276 + numIndices - The number of dof indices in the closure of point with the input sections 7277 . indices - The dof indices 7278 . outOffsets - Array to write the field offsets into, or NULL 7279 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7280 7281 Notes: 7282 Must call DMPlexRestoreClosureIndices() to free allocated memory 7283 7284 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7285 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7286 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7287 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7288 indices (with the above semantics) are implied. 7289 7290 Level: advanced 7291 7292 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7293 @*/ 7294 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7295 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7296 { 7297 /* Closure ordering */ 7298 PetscSection clSection; 7299 IS clPoints; 7300 const PetscInt *clp; 7301 PetscInt *points; 7302 const PetscInt *clperm = NULL; 7303 /* Dof permutation and sign flips */ 7304 const PetscInt **perms[32] = {NULL}; 7305 const PetscScalar **flips[32] = {NULL}; 7306 PetscScalar *valCopy = NULL; 7307 /* Hanging node constraints */ 7308 PetscInt *pointsC = NULL; 7309 PetscScalar *valuesC = NULL; 7310 PetscInt NclC, NiC; 7311 7312 PetscInt *idx; 7313 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7314 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7315 PetscErrorCode ierr; 7316 7317 PetscFunctionBeginHot; 7318 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7319 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7320 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7321 if (numIndices) PetscValidPointer(numIndices, 6); 7322 if (indices) PetscValidPointer(indices, 7); 7323 if (outOffsets) PetscValidPointer(outOffsets, 8); 7324 if (values) PetscValidPointer(values, 9); 7325 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7326 PetscCheckFalse(Nf > 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7327 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7328 /* 1) Get points in closure */ 7329 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7330 if (useClPerm) { 7331 PetscInt depth, clsize; 7332 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7333 for (clsize=0,p=0; p<Ncl; p++) { 7334 PetscInt dof; 7335 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7336 clsize += dof; 7337 } 7338 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7339 } 7340 /* 2) Get number of indices on these points and field offsets from section */ 7341 for (p = 0; p < Ncl*2; p += 2) { 7342 PetscInt dof, fdof; 7343 7344 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7345 for (f = 0; f < Nf; ++f) { 7346 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7347 offsets[f+1] += fdof; 7348 } 7349 Ni += dof; 7350 } 7351 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7352 PetscCheckFalse(Nf && offsets[Nf] != Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7353 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7354 for (f = 0; f < PetscMax(1, Nf); ++f) { 7355 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7356 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7357 /* may need to apply sign changes to the element matrix */ 7358 if (values && flips[f]) { 7359 PetscInt foffset = offsets[f]; 7360 7361 for (p = 0; p < Ncl; ++p) { 7362 PetscInt pnt = points[2*p], fdof; 7363 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7364 7365 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7366 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7367 if (flip) { 7368 PetscInt i, j, k; 7369 7370 if (!valCopy) { 7371 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7372 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7373 *values = valCopy; 7374 } 7375 for (i = 0; i < fdof; ++i) { 7376 PetscScalar fval = flip[i]; 7377 7378 for (k = 0; k < Ni; ++k) { 7379 valCopy[Ni * (foffset + i) + k] *= fval; 7380 valCopy[Ni * k + (foffset + i)] *= fval; 7381 } 7382 } 7383 } 7384 foffset += fdof; 7385 } 7386 } 7387 } 7388 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7389 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7390 if (NclC) { 7391 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7392 for (f = 0; f < PetscMax(1, Nf); ++f) { 7393 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7394 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7395 } 7396 for (f = 0; f < PetscMax(1, Nf); ++f) { 7397 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7398 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7399 } 7400 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7401 Ncl = NclC; 7402 Ni = NiC; 7403 points = pointsC; 7404 if (values) *values = valuesC; 7405 } 7406 /* 5) Calculate indices */ 7407 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7408 if (Nf) { 7409 PetscInt idxOff; 7410 PetscBool useFieldOffsets; 7411 7412 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7413 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7414 if (useFieldOffsets) { 7415 for (p = 0; p < Ncl; ++p) { 7416 const PetscInt pnt = points[p*2]; 7417 7418 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7419 } 7420 } else { 7421 for (p = 0; p < Ncl; ++p) { 7422 const PetscInt pnt = points[p*2]; 7423 7424 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7425 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7426 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7427 * global section. */ 7428 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7429 } 7430 } 7431 } else { 7432 PetscInt off = 0, idxOff; 7433 7434 for (p = 0; p < Ncl; ++p) { 7435 const PetscInt pnt = points[p*2]; 7436 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7437 7438 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7439 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7440 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7441 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7442 } 7443 } 7444 /* 6) Cleanup */ 7445 for (f = 0; f < PetscMax(1, Nf); ++f) { 7446 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7447 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7448 } 7449 if (NclC) { 7450 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7451 } else { 7452 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7453 } 7454 7455 if (numIndices) *numIndices = Ni; 7456 if (indices) *indices = idx; 7457 PetscFunctionReturn(0); 7458 } 7459 7460 /*@C 7461 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7462 7463 Not collective 7464 7465 Input Parameters: 7466 + dm - The DM 7467 . section - The PetscSection describing the points (a local section) 7468 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7469 . point - The point defining the closure 7470 - useClPerm - Use the closure point permutation if available 7471 7472 Output Parameters: 7473 + numIndices - The number of dof indices in the closure of point with the input sections 7474 . indices - The dof indices 7475 . outOffsets - Array to write the field offsets into, or NULL 7476 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7477 7478 Notes: 7479 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7480 7481 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7482 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7483 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7484 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7485 indices (with the above semantics) are implied. 7486 7487 Level: advanced 7488 7489 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7490 @*/ 7491 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7492 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7493 { 7494 PetscErrorCode ierr; 7495 7496 PetscFunctionBegin; 7497 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7498 PetscValidPointer(indices, 7); 7499 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7500 PetscFunctionReturn(0); 7501 } 7502 7503 /*@C 7504 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7505 7506 Not collective 7507 7508 Input Parameters: 7509 + dm - The DM 7510 . section - The section describing the layout in v, or NULL to use the default section 7511 . globalSection - The section describing the layout in v, or NULL to use the default global section 7512 . A - The matrix 7513 . point - The point in the DM 7514 . values - The array of values 7515 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7516 7517 Fortran Notes: 7518 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7519 7520 Level: intermediate 7521 7522 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7523 @*/ 7524 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7525 { 7526 DM_Plex *mesh = (DM_Plex*) dm->data; 7527 PetscInt *indices; 7528 PetscInt numIndices; 7529 const PetscScalar *valuesOrig = values; 7530 PetscErrorCode ierr; 7531 7532 PetscFunctionBegin; 7533 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7534 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7535 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7536 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7537 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7538 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7539 7540 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7541 7542 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7543 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7544 if (ierr) { 7545 PetscMPIInt rank; 7546 PetscErrorCode ierr2; 7547 7548 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7549 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7550 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7551 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7552 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7553 SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7554 } 7555 if (mesh->printFEM > 1) { 7556 PetscInt i; 7557 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7558 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7559 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7560 } 7561 7562 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7563 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7564 PetscFunctionReturn(0); 7565 } 7566 7567 /*@C 7568 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7569 7570 Not collective 7571 7572 Input Parameters: 7573 + dmRow - The DM for the row fields 7574 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7575 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7576 . dmCol - The DM for the column fields 7577 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7578 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7579 . A - The matrix 7580 . point - The point in the DMs 7581 . values - The array of values 7582 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7583 7584 Level: intermediate 7585 7586 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7587 @*/ 7588 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7589 { 7590 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7591 PetscInt *indicesRow, *indicesCol; 7592 PetscInt numIndicesRow, numIndicesCol; 7593 const PetscScalar *valuesOrig = values; 7594 PetscErrorCode ierr; 7595 7596 PetscFunctionBegin; 7597 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7598 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7599 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7600 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7601 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7602 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7603 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7604 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7605 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7606 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7607 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7608 7609 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7610 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7611 7612 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7613 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7614 if (ierr) { 7615 PetscMPIInt rank; 7616 PetscErrorCode ierr2; 7617 7618 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7619 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7620 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7621 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7622 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7623 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7624 CHKERRQ(ierr); 7625 } 7626 7627 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7628 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7629 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7630 PetscFunctionReturn(0); 7631 } 7632 7633 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7634 { 7635 DM_Plex *mesh = (DM_Plex*) dmf->data; 7636 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7637 PetscInt *cpoints = NULL; 7638 PetscInt *findices, *cindices; 7639 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7640 PetscInt foffsets[32], coffsets[32]; 7641 DMPolytopeType ct; 7642 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7643 PetscErrorCode ierr; 7644 7645 PetscFunctionBegin; 7646 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7647 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7648 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7649 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7650 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7651 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7652 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7653 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7654 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7655 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7656 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7657 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7658 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7659 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7660 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7661 /* Column indices */ 7662 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7663 maxFPoints = numCPoints; 7664 /* Compress out points not in the section */ 7665 /* TODO: Squeeze out points with 0 dof as well */ 7666 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7667 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7668 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7669 cpoints[q*2] = cpoints[p]; 7670 cpoints[q*2+1] = cpoints[p+1]; 7671 ++q; 7672 } 7673 } 7674 numCPoints = q; 7675 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7676 PetscInt fdof; 7677 7678 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7679 if (!dof) continue; 7680 for (f = 0; f < numFields; ++f) { 7681 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7682 coffsets[f+1] += fdof; 7683 } 7684 numCIndices += dof; 7685 } 7686 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7687 /* Row indices */ 7688 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7689 { 7690 DMPlexTransform tr; 7691 DMPolytopeType *rct; 7692 PetscInt *rsize, *rcone, *rornt, Nt; 7693 7694 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7695 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7696 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7697 numSubcells = rsize[Nt-1]; 7698 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7699 } 7700 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7701 for (r = 0, q = 0; r < numSubcells; ++r) { 7702 /* TODO Map from coarse to fine cells */ 7703 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7704 /* Compress out points not in the section */ 7705 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7706 for (p = 0; p < numFPoints*2; p += 2) { 7707 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7708 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7709 if (!dof) continue; 7710 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7711 if (s < q) continue; 7712 ftotpoints[q*2] = fpoints[p]; 7713 ftotpoints[q*2+1] = fpoints[p+1]; 7714 ++q; 7715 } 7716 } 7717 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7718 } 7719 numFPoints = q; 7720 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7721 PetscInt fdof; 7722 7723 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7724 if (!dof) continue; 7725 for (f = 0; f < numFields; ++f) { 7726 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7727 foffsets[f+1] += fdof; 7728 } 7729 numFIndices += dof; 7730 } 7731 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7732 7733 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7734 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7735 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7736 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7737 if (numFields) { 7738 const PetscInt **permsF[32] = {NULL}; 7739 const PetscInt **permsC[32] = {NULL}; 7740 7741 for (f = 0; f < numFields; f++) { 7742 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7743 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7744 } 7745 for (p = 0; p < numFPoints; p++) { 7746 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7747 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7748 } 7749 for (p = 0; p < numCPoints; p++) { 7750 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7751 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7752 } 7753 for (f = 0; f < numFields; f++) { 7754 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7755 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7756 } 7757 } else { 7758 const PetscInt **permsF = NULL; 7759 const PetscInt **permsC = NULL; 7760 7761 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7762 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7763 for (p = 0, off = 0; p < numFPoints; p++) { 7764 const PetscInt *perm = permsF ? permsF[p] : NULL; 7765 7766 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7767 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7768 } 7769 for (p = 0, off = 0; p < numCPoints; p++) { 7770 const PetscInt *perm = permsC ? permsC[p] : NULL; 7771 7772 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7773 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7774 } 7775 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7776 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7777 } 7778 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7779 /* TODO: flips */ 7780 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7781 if (ierr) { 7782 PetscMPIInt rank; 7783 PetscErrorCode ierr2; 7784 7785 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7786 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7787 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7788 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7789 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7790 CHKERRQ(ierr); 7791 } 7792 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7793 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7794 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7795 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7796 PetscFunctionReturn(0); 7797 } 7798 7799 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7800 { 7801 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7802 PetscInt *cpoints = NULL; 7803 PetscInt foffsets[32], coffsets[32]; 7804 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7805 DMPolytopeType ct; 7806 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7807 PetscErrorCode ierr; 7808 7809 PetscFunctionBegin; 7810 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7811 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7812 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7813 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7814 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7815 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7816 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7817 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7818 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7819 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7820 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7821 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7822 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7823 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7824 /* Column indices */ 7825 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7826 maxFPoints = numCPoints; 7827 /* Compress out points not in the section */ 7828 /* TODO: Squeeze out points with 0 dof as well */ 7829 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7830 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7831 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7832 cpoints[q*2] = cpoints[p]; 7833 cpoints[q*2+1] = cpoints[p+1]; 7834 ++q; 7835 } 7836 } 7837 numCPoints = q; 7838 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7839 PetscInt fdof; 7840 7841 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7842 if (!dof) continue; 7843 for (f = 0; f < numFields; ++f) { 7844 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7845 coffsets[f+1] += fdof; 7846 } 7847 numCIndices += dof; 7848 } 7849 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7850 /* Row indices */ 7851 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7852 { 7853 DMPlexTransform tr; 7854 DMPolytopeType *rct; 7855 PetscInt *rsize, *rcone, *rornt, Nt; 7856 7857 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7858 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7859 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7860 numSubcells = rsize[Nt-1]; 7861 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7862 } 7863 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7864 for (r = 0, q = 0; r < numSubcells; ++r) { 7865 /* TODO Map from coarse to fine cells */ 7866 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7867 /* Compress out points not in the section */ 7868 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7869 for (p = 0; p < numFPoints*2; p += 2) { 7870 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7871 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7872 if (!dof) continue; 7873 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7874 if (s < q) continue; 7875 ftotpoints[q*2] = fpoints[p]; 7876 ftotpoints[q*2+1] = fpoints[p+1]; 7877 ++q; 7878 } 7879 } 7880 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7881 } 7882 numFPoints = q; 7883 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7884 PetscInt fdof; 7885 7886 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7887 if (!dof) continue; 7888 for (f = 0; f < numFields; ++f) { 7889 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7890 foffsets[f+1] += fdof; 7891 } 7892 numFIndices += dof; 7893 } 7894 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7895 7896 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7897 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7898 if (numFields) { 7899 const PetscInt **permsF[32] = {NULL}; 7900 const PetscInt **permsC[32] = {NULL}; 7901 7902 for (f = 0; f < numFields; f++) { 7903 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7904 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7905 } 7906 for (p = 0; p < numFPoints; p++) { 7907 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7908 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7909 } 7910 for (p = 0; p < numCPoints; p++) { 7911 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7912 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7913 } 7914 for (f = 0; f < numFields; f++) { 7915 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7916 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7917 } 7918 } else { 7919 const PetscInt **permsF = NULL; 7920 const PetscInt **permsC = NULL; 7921 7922 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7923 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7924 for (p = 0, off = 0; p < numFPoints; p++) { 7925 const PetscInt *perm = permsF ? permsF[p] : NULL; 7926 7927 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7928 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7929 } 7930 for (p = 0, off = 0; p < numCPoints; p++) { 7931 const PetscInt *perm = permsC ? permsC[p] : NULL; 7932 7933 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7934 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7935 } 7936 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7937 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7938 } 7939 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7940 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7941 PetscFunctionReturn(0); 7942 } 7943 7944 /*@C 7945 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7946 7947 Input Parameter: 7948 . dm - The DMPlex object 7949 7950 Output Parameter: 7951 . cellHeight - The height of a cell 7952 7953 Level: developer 7954 7955 .seealso DMPlexSetVTKCellHeight() 7956 @*/ 7957 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7958 { 7959 DM_Plex *mesh = (DM_Plex*) dm->data; 7960 7961 PetscFunctionBegin; 7962 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7963 PetscValidPointer(cellHeight, 2); 7964 *cellHeight = mesh->vtkCellHeight; 7965 PetscFunctionReturn(0); 7966 } 7967 7968 /*@C 7969 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7970 7971 Input Parameters: 7972 + dm - The DMPlex object 7973 - cellHeight - The height of a cell 7974 7975 Level: developer 7976 7977 .seealso DMPlexGetVTKCellHeight() 7978 @*/ 7979 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7980 { 7981 DM_Plex *mesh = (DM_Plex*) dm->data; 7982 7983 PetscFunctionBegin; 7984 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7985 mesh->vtkCellHeight = cellHeight; 7986 PetscFunctionReturn(0); 7987 } 7988 7989 /*@ 7990 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7991 7992 Input Parameter: 7993 . dm - The DMPlex object 7994 7995 Output Parameters: 7996 + gcStart - The first ghost cell, or NULL 7997 - gcEnd - The upper bound on ghost cells, or NULL 7998 7999 Level: advanced 8000 8001 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 8002 @*/ 8003 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 8004 { 8005 DMLabel ctLabel; 8006 PetscErrorCode ierr; 8007 8008 PetscFunctionBegin; 8009 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8010 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 8011 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 8012 PetscFunctionReturn(0); 8013 } 8014 8015 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8016 { 8017 PetscSection section, globalSection; 8018 PetscInt *numbers, p; 8019 PetscErrorCode ierr; 8020 8021 PetscFunctionBegin; 8022 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8023 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 8024 for (p = pStart; p < pEnd; ++p) { 8025 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 8026 } 8027 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 8028 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8029 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 8030 for (p = pStart; p < pEnd; ++p) { 8031 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 8032 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8033 else numbers[p-pStart] += shift; 8034 } 8035 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 8036 if (globalSize) { 8037 PetscLayout layout; 8038 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 8039 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 8040 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 8041 } 8042 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8043 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8044 PetscFunctionReturn(0); 8045 } 8046 8047 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8048 { 8049 PetscInt cellHeight, cStart, cEnd; 8050 PetscErrorCode ierr; 8051 8052 PetscFunctionBegin; 8053 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8054 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8055 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8056 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 8057 PetscFunctionReturn(0); 8058 } 8059 8060 /*@ 8061 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 8062 8063 Input Parameter: 8064 . dm - The DMPlex object 8065 8066 Output Parameter: 8067 . globalCellNumbers - Global cell numbers for all cells on this process 8068 8069 Level: developer 8070 8071 .seealso DMPlexGetVertexNumbering() 8072 @*/ 8073 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8074 { 8075 DM_Plex *mesh = (DM_Plex*) dm->data; 8076 PetscErrorCode ierr; 8077 8078 PetscFunctionBegin; 8079 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8080 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 8081 *globalCellNumbers = mesh->globalCellNumbers; 8082 PetscFunctionReturn(0); 8083 } 8084 8085 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8086 { 8087 PetscInt vStart, vEnd; 8088 PetscErrorCode ierr; 8089 8090 PetscFunctionBegin; 8091 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8092 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8093 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 8094 PetscFunctionReturn(0); 8095 } 8096 8097 /*@ 8098 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 8099 8100 Input Parameter: 8101 . dm - The DMPlex object 8102 8103 Output Parameter: 8104 . globalVertexNumbers - Global vertex numbers for all vertices on this process 8105 8106 Level: developer 8107 8108 .seealso DMPlexGetCellNumbering() 8109 @*/ 8110 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8111 { 8112 DM_Plex *mesh = (DM_Plex*) dm->data; 8113 PetscErrorCode ierr; 8114 8115 PetscFunctionBegin; 8116 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8117 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 8118 *globalVertexNumbers = mesh->globalVertexNumbers; 8119 PetscFunctionReturn(0); 8120 } 8121 8122 /*@ 8123 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 8124 8125 Input Parameter: 8126 . dm - The DMPlex object 8127 8128 Output Parameter: 8129 . globalPointNumbers - Global numbers for all points on this process 8130 8131 Level: developer 8132 8133 .seealso DMPlexGetCellNumbering() 8134 @*/ 8135 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8136 { 8137 IS nums[4]; 8138 PetscInt depths[4], gdepths[4], starts[4]; 8139 PetscInt depth, d, shift = 0; 8140 PetscErrorCode ierr; 8141 8142 PetscFunctionBegin; 8143 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8144 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8145 /* For unstratified meshes use dim instead of depth */ 8146 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 8147 for (d = 0; d <= depth; ++d) { 8148 PetscInt end; 8149 8150 depths[d] = depth-d; 8151 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 8152 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8153 } 8154 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 8155 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8156 for (d = 0; d <= depth; ++d) { 8157 PetscCheckFalse(starts[d] >= 0 && depths[d] != gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8158 } 8159 for (d = 0; d <= depth; ++d) { 8160 PetscInt pStart, pEnd, gsize; 8161 8162 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 8163 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 8164 shift += gsize; 8165 } 8166 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 8167 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 8168 PetscFunctionReturn(0); 8169 } 8170 8171 /*@ 8172 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 8173 8174 Input Parameter: 8175 . dm - The DMPlex object 8176 8177 Output Parameter: 8178 . ranks - The rank field 8179 8180 Options Database Keys: 8181 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 8182 8183 Level: intermediate 8184 8185 .seealso: DMView() 8186 @*/ 8187 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8188 { 8189 DM rdm; 8190 PetscFE fe; 8191 PetscScalar *r; 8192 PetscMPIInt rank; 8193 DMPolytopeType ct; 8194 PetscInt dim, cStart, cEnd, c; 8195 PetscBool simplex; 8196 PetscErrorCode ierr; 8197 8198 PetscFunctionBeginUser; 8199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8200 PetscValidPointer(ranks, 2); 8201 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 8202 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8203 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8204 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8205 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 8206 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 8207 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 8208 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 8209 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8210 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8211 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8212 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 8213 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 8214 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 8215 for (c = cStart; c < cEnd; ++c) { 8216 PetscScalar *lr; 8217 8218 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 8219 if (lr) *lr = rank; 8220 } 8221 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8222 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8223 PetscFunctionReturn(0); 8224 } 8225 8226 /*@ 8227 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8228 8229 Input Parameters: 8230 + dm - The DMPlex 8231 - label - The DMLabel 8232 8233 Output Parameter: 8234 . val - The label value field 8235 8236 Options Database Keys: 8237 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8238 8239 Level: intermediate 8240 8241 .seealso: DMView() 8242 @*/ 8243 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8244 { 8245 DM rdm; 8246 PetscFE fe; 8247 PetscScalar *v; 8248 PetscInt dim, cStart, cEnd, c; 8249 PetscErrorCode ierr; 8250 8251 PetscFunctionBeginUser; 8252 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8253 PetscValidPointer(label, 2); 8254 PetscValidPointer(val, 3); 8255 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8256 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8257 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8258 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8259 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8260 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8261 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8262 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8263 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8264 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8265 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8266 for (c = cStart; c < cEnd; ++c) { 8267 PetscScalar *lv; 8268 PetscInt cval; 8269 8270 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8271 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8272 *lv = cval; 8273 } 8274 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8275 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8276 PetscFunctionReturn(0); 8277 } 8278 8279 /*@ 8280 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8281 8282 Input Parameter: 8283 . dm - The DMPlex object 8284 8285 Notes: 8286 This is a useful diagnostic when creating meshes programmatically. 8287 8288 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8289 8290 Level: developer 8291 8292 .seealso: DMCreate(), DMSetFromOptions() 8293 @*/ 8294 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8295 { 8296 PetscSection coneSection, supportSection; 8297 const PetscInt *cone, *support; 8298 PetscInt coneSize, c, supportSize, s; 8299 PetscInt pStart, pEnd, p, pp, csize, ssize; 8300 PetscBool storagecheck = PETSC_TRUE; 8301 PetscErrorCode ierr; 8302 8303 PetscFunctionBegin; 8304 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8305 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8306 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8307 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8308 /* Check that point p is found in the support of its cone points, and vice versa */ 8309 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8310 for (p = pStart; p < pEnd; ++p) { 8311 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8312 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8313 for (c = 0; c < coneSize; ++c) { 8314 PetscBool dup = PETSC_FALSE; 8315 PetscInt d; 8316 for (d = c-1; d >= 0; --d) { 8317 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8318 } 8319 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8320 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8321 for (s = 0; s < supportSize; ++s) { 8322 if (support[s] == p) break; 8323 } 8324 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8325 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8326 for (s = 0; s < coneSize; ++s) { 8327 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8328 } 8329 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8330 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8331 for (s = 0; s < supportSize; ++s) { 8332 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8333 } 8334 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8335 PetscCheckFalse(dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8336 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8337 } 8338 } 8339 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8340 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8341 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8342 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8343 for (s = 0; s < supportSize; ++s) { 8344 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8345 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8346 for (c = 0; c < coneSize; ++c) { 8347 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8348 if (cone[c] != pp) { c = 0; break; } 8349 if (cone[c] == p) break; 8350 } 8351 if (c >= coneSize) { 8352 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8353 for (c = 0; c < supportSize; ++c) { 8354 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8355 } 8356 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8357 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8358 for (c = 0; c < coneSize; ++c) { 8359 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8360 } 8361 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8362 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8363 } 8364 } 8365 } 8366 if (storagecheck) { 8367 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8368 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8369 PetscCheckFalse(csize != ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8370 } 8371 PetscFunctionReturn(0); 8372 } 8373 8374 /* 8375 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. 8376 */ 8377 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8378 { 8379 DMPolytopeType cct; 8380 PetscInt ptpoints[4]; 8381 const PetscInt *cone, *ccone, *ptcone; 8382 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8383 PetscErrorCode ierr; 8384 8385 PetscFunctionBegin; 8386 *unsplit = 0; 8387 switch (ct) { 8388 case DM_POLYTOPE_POINT_PRISM_TENSOR: 8389 ptpoints[npt++] = c; 8390 break; 8391 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8392 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8393 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8394 for (cp = 0; cp < coneSize; ++cp) { 8395 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8396 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8397 } 8398 break; 8399 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8400 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8401 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8402 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8403 for (cp = 0; cp < coneSize; ++cp) { 8404 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8405 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8406 for (ccp = 0; ccp < cconeSize; ++ccp) { 8407 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8408 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8409 PetscInt p; 8410 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8411 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8412 } 8413 } 8414 } 8415 break; 8416 default: break; 8417 } 8418 for (pt = 0; pt < npt; ++pt) { 8419 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8420 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8421 } 8422 PetscFunctionReturn(0); 8423 } 8424 8425 /*@ 8426 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8427 8428 Input Parameters: 8429 + dm - The DMPlex object 8430 - cellHeight - Normally 0 8431 8432 Notes: 8433 This is a useful diagnostic when creating meshes programmatically. 8434 Currently applicable only to homogeneous simplex or tensor meshes. 8435 8436 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8437 8438 Level: developer 8439 8440 .seealso: DMCreate(), DMSetFromOptions() 8441 @*/ 8442 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8443 { 8444 DMPlexInterpolatedFlag interp; 8445 DMPolytopeType ct; 8446 PetscInt vStart, vEnd, cStart, cEnd, c; 8447 PetscErrorCode ierr; 8448 8449 PetscFunctionBegin; 8450 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8451 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8452 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8453 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8454 for (c = cStart; c < cEnd; ++c) { 8455 PetscInt *closure = NULL; 8456 PetscInt coneSize, closureSize, cl, Nv = 0; 8457 8458 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8459 PetscCheckFalse((PetscInt) ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8460 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8461 if (interp == DMPLEX_INTERPOLATED_FULL) { 8462 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8463 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)); 8464 } 8465 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8466 for (cl = 0; cl < closureSize*2; cl += 2) { 8467 const PetscInt p = closure[cl]; 8468 if ((p >= vStart) && (p < vEnd)) ++Nv; 8469 } 8470 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8471 /* Special Case: Tensor faces with identified vertices */ 8472 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8473 PetscInt unsplit; 8474 8475 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8476 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8477 } 8478 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)); 8479 } 8480 PetscFunctionReturn(0); 8481 } 8482 8483 /*@ 8484 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8485 8486 Not Collective 8487 8488 Input Parameters: 8489 + dm - The DMPlex object 8490 - cellHeight - Normally 0 8491 8492 Notes: 8493 This is a useful diagnostic when creating meshes programmatically. 8494 This routine is only relevant for meshes that are fully interpolated across all ranks. 8495 It will error out if a partially interpolated mesh is given on some rank. 8496 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8497 8498 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8499 8500 Level: developer 8501 8502 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8503 @*/ 8504 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8505 { 8506 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8507 PetscErrorCode ierr; 8508 DMPlexInterpolatedFlag interpEnum; 8509 8510 PetscFunctionBegin; 8511 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8512 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8513 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8514 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8515 PetscMPIInt rank; 8516 MPI_Comm comm; 8517 8518 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8519 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8520 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8521 } 8522 8523 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8524 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8525 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8526 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8527 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8528 for (c = cStart; c < cEnd; ++c) { 8529 const PetscInt *cone, *ornt, *faceSizes, *faces; 8530 const DMPolytopeType *faceTypes; 8531 DMPolytopeType ct; 8532 PetscInt numFaces, coneSize, f; 8533 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8534 8535 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8536 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8537 if (unsplit) continue; 8538 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8539 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8540 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8541 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8542 for (cl = 0; cl < closureSize*2; cl += 2) { 8543 const PetscInt p = closure[cl]; 8544 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8545 } 8546 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8547 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); 8548 for (f = 0; f < numFaces; ++f) { 8549 DMPolytopeType fct; 8550 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8551 8552 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8553 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8554 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8555 const PetscInt p = fclosure[cl]; 8556 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8557 } 8558 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]); 8559 for (v = 0; v < fnumCorners; ++v) { 8560 if (fclosure[v] != faces[fOff+v]) { 8561 PetscInt v1; 8562 8563 ierr = PetscPrintf(PETSC_COMM_SELF, "face closure:");CHKERRQ(ierr); 8564 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]);CHKERRQ(ierr);} 8565 ierr = PetscPrintf(PETSC_COMM_SELF, "\ncell face:");CHKERRQ(ierr); 8566 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]);CHKERRQ(ierr);} 8567 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8568 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]); 8569 } 8570 } 8571 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8572 fOff += faceSizes[f]; 8573 } 8574 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8575 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8576 } 8577 } 8578 PetscFunctionReturn(0); 8579 } 8580 8581 /*@ 8582 DMPlexCheckGeometry - Check the geometry of mesh cells 8583 8584 Input Parameter: 8585 . dm - The DMPlex object 8586 8587 Notes: 8588 This is a useful diagnostic when creating meshes programmatically. 8589 8590 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8591 8592 Level: developer 8593 8594 .seealso: DMCreate(), DMSetFromOptions() 8595 @*/ 8596 PetscErrorCode DMPlexCheckGeometry(DM dm) 8597 { 8598 Vec coordinates; 8599 PetscReal detJ, J[9], refVol = 1.0; 8600 PetscReal vol; 8601 PetscBool periodic; 8602 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8603 PetscErrorCode ierr; 8604 8605 PetscFunctionBegin; 8606 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8607 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8608 if (dim != dE) PetscFunctionReturn(0); 8609 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8610 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8611 for (d = 0; d < dim; ++d) refVol *= 2.0; 8612 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8613 /* Make sure local coordinates are created, because that step is collective */ 8614 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8615 for (c = cStart; c < cEnd; ++c) { 8616 DMPolytopeType ct; 8617 PetscInt unsplit; 8618 PetscBool ignoreZeroVol = PETSC_FALSE; 8619 8620 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8621 switch (ct) { 8622 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8623 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8624 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8625 ignoreZeroVol = PETSC_TRUE; break; 8626 default: break; 8627 } 8628 switch (ct) { 8629 case DM_POLYTOPE_TRI_PRISM: 8630 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8631 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8632 case DM_POLYTOPE_PYRAMID: 8633 continue; 8634 default: break; 8635 } 8636 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8637 if (unsplit) continue; 8638 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8639 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); 8640 ierr = PetscInfo(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8641 if (depth > 1 && !periodic) { 8642 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8643 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); 8644 ierr = PetscInfo(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8645 } 8646 } 8647 PetscFunctionReturn(0); 8648 } 8649 8650 /*@ 8651 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8652 8653 Input Parameters: 8654 . dm - The DMPlex object 8655 8656 Notes: 8657 This is mainly intended for debugging/testing purposes. 8658 It currently checks only meshes with no partition overlapping. 8659 8660 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8661 8662 Level: developer 8663 8664 .seealso: DMGetPointSF(), DMSetFromOptions() 8665 @*/ 8666 PetscErrorCode DMPlexCheckPointSF(DM dm) 8667 { 8668 PetscSF pointSF; 8669 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8670 const PetscInt *locals, *rootdegree; 8671 PetscBool distributed; 8672 PetscErrorCode ierr; 8673 8674 PetscFunctionBegin; 8675 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8676 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8677 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8678 if (!distributed) PetscFunctionReturn(0); 8679 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8680 if (overlap) { 8681 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8682 PetscFunctionReturn(0); 8683 } 8684 PetscCheckFalse(!pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8685 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8686 PetscCheckFalse(nroots < 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8687 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8688 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8689 8690 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8691 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8692 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8693 for (l = 0; l < nleaves; ++l) { 8694 const PetscInt point = locals[l]; 8695 8696 PetscCheckFalse(point >= cStart && point < cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8697 } 8698 8699 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8700 for (l = 0; l < nleaves; ++l) { 8701 const PetscInt point = locals[l]; 8702 const PetscInt *cone; 8703 PetscInt coneSize, c, idx; 8704 8705 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8706 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8707 for (c = 0; c < coneSize; ++c) { 8708 if (!rootdegree[cone[c]]) { 8709 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8710 PetscCheckFalse(idx < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8711 } 8712 } 8713 } 8714 PetscFunctionReturn(0); 8715 } 8716 8717 PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8718 { 8719 PetscErrorCode ierr; 8720 8721 PetscFunctionBegin; 8722 ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr); 8723 ierr = DMPlexCheckSkeleton(dm, cellHeight);CHKERRQ(ierr); 8724 ierr = DMPlexCheckFaces(dm, cellHeight);CHKERRQ(ierr); 8725 ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr); 8726 ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 8727 ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr); 8728 PetscFunctionReturn(0); 8729 } 8730 8731 typedef struct cell_stats 8732 { 8733 PetscReal min, max, sum, squaresum; 8734 PetscInt count; 8735 } cell_stats_t; 8736 8737 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8738 { 8739 PetscInt i, N = *len; 8740 8741 for (i = 0; i < N; i++) { 8742 cell_stats_t *A = (cell_stats_t *) a; 8743 cell_stats_t *B = (cell_stats_t *) b; 8744 8745 B->min = PetscMin(A->min,B->min); 8746 B->max = PetscMax(A->max,B->max); 8747 B->sum += A->sum; 8748 B->squaresum += A->squaresum; 8749 B->count += A->count; 8750 } 8751 } 8752 8753 /*@ 8754 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8755 8756 Collective on dm 8757 8758 Input Parameters: 8759 + dm - The DMPlex object 8760 . output - If true, statistics will be displayed on stdout 8761 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8762 8763 Notes: 8764 This is mainly intended for debugging/testing purposes. 8765 8766 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8767 8768 Level: developer 8769 8770 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8771 @*/ 8772 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8773 { 8774 DM dmCoarse; 8775 cell_stats_t stats, globalStats; 8776 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8777 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8778 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8779 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8780 PetscMPIInt rank,size; 8781 PetscErrorCode ierr; 8782 8783 PetscFunctionBegin; 8784 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8785 stats.min = PETSC_MAX_REAL; 8786 stats.max = PETSC_MIN_REAL; 8787 stats.sum = stats.squaresum = 0.; 8788 stats.count = 0; 8789 8790 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8791 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8792 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8793 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8794 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8795 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8796 for (c = cStart; c < cEnd; c++) { 8797 PetscInt i; 8798 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8799 8800 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8801 PetscCheckFalse(detJ < 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8802 for (i = 0; i < PetscSqr(cdim); ++i) { 8803 frobJ += J[i] * J[i]; 8804 frobInvJ += invJ[i] * invJ[i]; 8805 } 8806 cond2 = frobJ * frobInvJ; 8807 cond = PetscSqrtReal(cond2); 8808 8809 stats.min = PetscMin(stats.min,cond); 8810 stats.max = PetscMax(stats.max,cond); 8811 stats.sum += cond; 8812 stats.squaresum += cond2; 8813 stats.count++; 8814 if (output && cond > limit) { 8815 PetscSection coordSection; 8816 Vec coordsLocal; 8817 PetscScalar *coords = NULL; 8818 PetscInt Nv, d, clSize, cl, *closure = NULL; 8819 8820 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8821 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8822 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8823 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8824 for (i = 0; i < Nv/cdim; ++i) { 8825 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8826 for (d = 0; d < cdim; ++d) { 8827 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8828 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8829 } 8830 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8831 } 8832 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8833 for (cl = 0; cl < clSize*2; cl += 2) { 8834 const PetscInt edge = closure[cl]; 8835 8836 if ((edge >= eStart) && (edge < eEnd)) { 8837 PetscReal len; 8838 8839 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8840 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8841 } 8842 } 8843 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8844 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8845 } 8846 } 8847 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8848 8849 if (size > 1) { 8850 PetscMPIInt blockLengths[2] = {4,1}; 8851 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8852 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8853 MPI_Op statReduce; 8854 8855 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8856 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8857 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8858 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8859 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8860 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8861 } else { 8862 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8863 } 8864 if (rank == 0) { 8865 count = globalStats.count; 8866 min = globalStats.min; 8867 max = globalStats.max; 8868 mean = globalStats.sum / globalStats.count; 8869 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8870 } 8871 8872 if (output) { 8873 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); 8874 } 8875 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8876 8877 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8878 if (dmCoarse) { 8879 PetscBool isplex; 8880 8881 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8882 if (isplex) { 8883 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8884 } 8885 } 8886 PetscFunctionReturn(0); 8887 } 8888 8889 /*@ 8890 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8891 orthogonal quality below given tolerance. 8892 8893 Collective on dm 8894 8895 Input Parameters: 8896 + dm - The DMPlex object 8897 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8898 - atol - [0, 1] Absolute tolerance for tagging cells. 8899 8900 Output Parameters: 8901 + OrthQual - Vec containing orthogonal quality per cell 8902 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8903 8904 Options Database Keys: 8905 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8906 supported. 8907 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8908 8909 Notes: 8910 Orthogonal quality is given by the following formula: 8911 8912 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8913 8914 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 8915 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8916 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8917 calculating the cosine of the angle between these vectors. 8918 8919 Orthogonal quality ranges from 1 (best) to 0 (worst). 8920 8921 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8922 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8923 8924 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8925 8926 Level: intermediate 8927 8928 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8929 @*/ 8930 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8931 { 8932 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8933 PetscInt *idx; 8934 PetscScalar *oqVals; 8935 const PetscScalar *cellGeomArr, *faceGeomArr; 8936 PetscReal *ci, *fi, *Ai; 8937 MPI_Comm comm; 8938 Vec cellgeom, facegeom; 8939 DM dmFace, dmCell; 8940 IS glob; 8941 ISLocalToGlobalMapping ltog; 8942 PetscViewer vwr; 8943 PetscErrorCode ierr; 8944 8945 PetscFunctionBegin; 8946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8947 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8948 PetscValidPointer(OrthQual, 4); 8949 PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 8950 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8951 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8952 PetscCheckFalse(nc < 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8953 { 8954 DMPlexInterpolatedFlag interpFlag; 8955 8956 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8957 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8958 PetscMPIInt rank; 8959 8960 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8961 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8962 } 8963 } 8964 if (OrthQualLabel) { 8965 PetscValidPointer(OrthQualLabel, 5); 8966 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8967 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8968 } else {*OrthQualLabel = NULL;} 8969 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8970 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8971 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8972 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8973 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8974 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8975 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8976 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8977 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8978 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8979 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8980 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8981 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8982 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8983 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8984 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8985 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8986 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8987 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8988 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8989 PetscInt cellarr[2], *adj = NULL; 8990 PetscScalar *cArr, *fArr; 8991 PetscReal minvalc = 1.0, minvalf = 1.0; 8992 PetscFVCellGeom *cg; 8993 8994 idx[cellIter] = cell-cStart; 8995 cellarr[0] = cell; 8996 /* Make indexing into cellGeom easier */ 8997 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 8998 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 8999 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 9000 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 9001 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 9002 PetscInt i; 9003 const PetscInt neigh = adj[cellneigh]; 9004 PetscReal normci = 0, normfi = 0, normai = 0; 9005 PetscFVCellGeom *cgneigh; 9006 PetscFVFaceGeom *fg; 9007 9008 /* Don't count ourselves in the neighbor list */ 9009 if (neigh == cell) continue; 9010 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 9011 cellarr[1] = neigh; 9012 { 9013 PetscInt numcovpts; 9014 const PetscInt *covpts; 9015 9016 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9017 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 9018 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9019 } 9020 9021 /* Compute c_i, f_i and their norms */ 9022 for (i = 0; i < nc; i++) { 9023 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9024 fi[i] = fg->centroid[i] - cg->centroid[i]; 9025 Ai[i] = fg->normal[i]; 9026 normci += PetscPowReal(ci[i], 2); 9027 normfi += PetscPowReal(fi[i], 2); 9028 normai += PetscPowReal(Ai[i], 2); 9029 } 9030 normci = PetscSqrtReal(normci); 9031 normfi = PetscSqrtReal(normfi); 9032 normai = PetscSqrtReal(normai); 9033 9034 /* Normalize and compute for each face-cell-normal pair */ 9035 for (i = 0; i < nc; i++) { 9036 ci[i] = ci[i]/normci; 9037 fi[i] = fi[i]/normfi; 9038 Ai[i] = Ai[i]/normai; 9039 /* PetscAbs because I don't know if normals are guaranteed to point out */ 9040 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9041 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9042 } 9043 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9044 minvalc = PetscRealPart(cArr[cellneighiter]); 9045 } 9046 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9047 minvalf = PetscRealPart(fArr[cellneighiter]); 9048 } 9049 } 9050 ierr = PetscFree(adj);CHKERRQ(ierr); 9051 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 9052 /* Defer to cell if they're equal */ 9053 oqVals[cellIter] = PetscMin(minvalf, minvalc); 9054 if (OrthQualLabel) { 9055 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 9056 } 9057 } 9058 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 9059 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 9060 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 9061 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 9062 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 9063 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 9064 if (OrthQualLabel) { 9065 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 9066 } 9067 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 9068 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 9069 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 9070 PetscFunctionReturn(0); 9071 } 9072 9073 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 9074 * interpolator construction */ 9075 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9076 { 9077 PetscSection section, newSection, gsection; 9078 PetscSF sf; 9079 PetscBool hasConstraints, ghasConstraints; 9080 PetscErrorCode ierr; 9081 9082 PetscFunctionBegin; 9083 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9084 PetscValidPointer(odm,2); 9085 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9086 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 9087 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 9088 if (!ghasConstraints) { 9089 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 9090 *odm = dm; 9091 PetscFunctionReturn(0); 9092 } 9093 ierr = DMClone(dm, odm);CHKERRQ(ierr); 9094 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 9095 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 9096 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 9097 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 9098 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 9099 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 9100 PetscFunctionReturn(0); 9101 } 9102 9103 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9104 { 9105 DM dmco, dmfo; 9106 Mat interpo; 9107 Vec rscale; 9108 Vec cglobalo, clocal; 9109 Vec fglobal, fglobalo, flocal; 9110 PetscBool regular; 9111 PetscErrorCode ierr; 9112 9113 PetscFunctionBegin; 9114 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 9115 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 9116 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 9117 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 9118 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 9119 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 9120 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 9121 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 9122 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 9123 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 9124 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 9125 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 9126 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 9127 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 9128 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 9129 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 9130 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 9131 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9132 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9133 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 9134 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9135 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9136 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9137 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9138 *shift = fglobal; 9139 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 9140 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 9141 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 9142 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 9143 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9144 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 9145 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 9146 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 9147 PetscFunctionReturn(0); 9148 } 9149 9150 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9151 { 9152 PetscObject shifto; 9153 Vec shift; 9154 9155 PetscErrorCode ierr; 9156 9157 PetscFunctionBegin; 9158 if (!interp) { 9159 Vec rscale; 9160 9161 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 9162 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9163 } else { 9164 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 9165 } 9166 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 9167 if (!shifto) { 9168 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 9169 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 9170 shifto = (PetscObject) shift; 9171 ierr = VecDestroy(&shift);CHKERRQ(ierr); 9172 } 9173 shift = (Vec) shifto; 9174 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 9175 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 9176 ierr = MatDestroy(&interp);CHKERRQ(ierr); 9177 PetscFunctionReturn(0); 9178 } 9179 9180 /* Pointwise interpolation 9181 Just code FEM for now 9182 u^f = I u^c 9183 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 9184 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 9185 I_{ij} = psi^f_i phi^c_j 9186 */ 9187 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9188 { 9189 PetscSection gsc, gsf; 9190 PetscInt m, n; 9191 void *ctx; 9192 DM cdm; 9193 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9194 PetscErrorCode ierr; 9195 9196 PetscFunctionBegin; 9197 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9198 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9199 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9200 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9201 9202 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 9203 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 9204 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9205 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 9206 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9207 9208 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9209 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9210 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 9211 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 9212 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 9213 if (scaling) { 9214 /* Use naive scaling */ 9215 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 9216 } 9217 PetscFunctionReturn(0); 9218 } 9219 9220 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9221 { 9222 PetscErrorCode ierr; 9223 VecScatter ctx; 9224 9225 PetscFunctionBegin; 9226 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 9227 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 9228 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 9229 PetscFunctionReturn(0); 9230 } 9231 9232 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9233 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9234 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9235 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9236 { 9237 const PetscInt Nc = uOff[1] - uOff[0]; 9238 PetscInt c; 9239 for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 9240 } 9241 9242 PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9243 { 9244 DM dmc; 9245 PetscDS ds; 9246 Vec ones, locmass; 9247 IS cellIS; 9248 PetscFormKey key; 9249 PetscInt depth; 9250 PetscErrorCode ierr; 9251 9252 PetscFunctionBegin; 9253 ierr = DMClone(dm, &dmc);CHKERRQ(ierr); 9254 ierr = DMCopyDisc(dm, dmc);CHKERRQ(ierr); 9255 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9256 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9257 ierr = DMCreateGlobalVector(dmc, mass);CHKERRQ(ierr); 9258 ierr = DMGetLocalVector(dmc, &ones);CHKERRQ(ierr); 9259 ierr = DMGetLocalVector(dmc, &locmass);CHKERRQ(ierr); 9260 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9261 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9262 ierr = VecSet(locmass, 0.0);CHKERRQ(ierr); 9263 ierr = VecSet(ones, 1.0);CHKERRQ(ierr); 9264 key.label = NULL; 9265 key.value = 0; 9266 key.field = 0; 9267 key.part = 0; 9268 ierr = DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL);CHKERRQ(ierr); 9269 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9270 ierr = VecSet(*mass, 0.0);CHKERRQ(ierr); 9271 ierr = DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9272 ierr = DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9273 ierr = DMRestoreLocalVector(dmc, &ones);CHKERRQ(ierr); 9274 ierr = DMRestoreLocalVector(dmc, &locmass);CHKERRQ(ierr); 9275 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9276 PetscFunctionReturn(0); 9277 } 9278 9279 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9280 { 9281 PetscSection gsc, gsf; 9282 PetscInt m, n; 9283 void *ctx; 9284 DM cdm; 9285 PetscBool regular; 9286 PetscErrorCode ierr; 9287 9288 PetscFunctionBegin; 9289 if (dmFine == dmCoarse) { 9290 DM dmc; 9291 PetscDS ds; 9292 PetscWeakForm wf; 9293 Vec u; 9294 IS cellIS; 9295 PetscFormKey key; 9296 PetscInt depth; 9297 9298 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9299 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9300 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9301 ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 9302 ierr = PetscWeakFormClear(wf);CHKERRQ(ierr); 9303 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9304 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9305 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9306 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9307 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9308 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9309 key.label = NULL; 9310 key.value = 0; 9311 key.field = 0; 9312 key.part = 0; 9313 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9314 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9315 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9316 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9317 } else { 9318 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9319 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9320 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9321 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9322 9323 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9324 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9325 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9326 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9327 9328 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9329 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9330 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9331 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9332 } 9333 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9334 PetscFunctionReturn(0); 9335 } 9336 9337 /*@ 9338 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9339 9340 Input Parameter: 9341 . dm - The DMPlex object 9342 9343 Output Parameter: 9344 . regular - The flag 9345 9346 Level: intermediate 9347 9348 .seealso: DMPlexSetRegularRefinement() 9349 @*/ 9350 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9351 { 9352 PetscFunctionBegin; 9353 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9354 PetscValidPointer(regular, 2); 9355 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9356 PetscFunctionReturn(0); 9357 } 9358 9359 /*@ 9360 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9361 9362 Input Parameters: 9363 + dm - The DMPlex object 9364 - regular - The flag 9365 9366 Level: intermediate 9367 9368 .seealso: DMPlexGetRegularRefinement() 9369 @*/ 9370 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9371 { 9372 PetscFunctionBegin; 9373 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9374 ((DM_Plex *) dm->data)->regularRefinement = regular; 9375 PetscFunctionReturn(0); 9376 } 9377 9378 /* anchors */ 9379 /*@ 9380 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9381 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9382 9383 not collective 9384 9385 Input Parameter: 9386 . dm - The DMPlex object 9387 9388 Output Parameters: 9389 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9390 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9391 9392 Level: intermediate 9393 9394 .seealso: DMPlexSetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9395 @*/ 9396 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9397 { 9398 DM_Plex *plex = (DM_Plex *)dm->data; 9399 PetscErrorCode ierr; 9400 9401 PetscFunctionBegin; 9402 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9403 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9404 if (anchorSection) *anchorSection = plex->anchorSection; 9405 if (anchorIS) *anchorIS = plex->anchorIS; 9406 PetscFunctionReturn(0); 9407 } 9408 9409 /*@ 9410 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9411 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9412 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9413 9414 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9415 DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9416 9417 collective on dm 9418 9419 Input Parameters: 9420 + dm - The DMPlex object 9421 . 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). 9422 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9423 9424 The reference counts of anchorSection and anchorIS are incremented. 9425 9426 Level: intermediate 9427 9428 .seealso: DMPlexGetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9429 @*/ 9430 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9431 { 9432 DM_Plex *plex = (DM_Plex *)dm->data; 9433 PetscMPIInt result; 9434 PetscErrorCode ierr; 9435 9436 PetscFunctionBegin; 9437 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9438 if (anchorSection) { 9439 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9440 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9441 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9442 } 9443 if (anchorIS) { 9444 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9445 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9446 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9447 } 9448 9449 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9450 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9451 plex->anchorSection = anchorSection; 9452 9453 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9454 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9455 plex->anchorIS = anchorIS; 9456 9457 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9458 PetscInt size, a, pStart, pEnd; 9459 const PetscInt *anchors; 9460 9461 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9462 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9463 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9464 for (a = 0; a < size; a++) { 9465 PetscInt p; 9466 9467 p = anchors[a]; 9468 if (p >= pStart && p < pEnd) { 9469 PetscInt dof; 9470 9471 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9472 if (dof) { 9473 PetscErrorCode ierr2; 9474 9475 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9476 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9477 } 9478 } 9479 } 9480 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9481 } 9482 /* reset the generic constraints */ 9483 ierr = DMSetDefaultConstraints(dm,NULL,NULL,NULL);CHKERRQ(ierr); 9484 PetscFunctionReturn(0); 9485 } 9486 9487 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9488 { 9489 PetscSection anchorSection; 9490 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9491 PetscErrorCode ierr; 9492 9493 PetscFunctionBegin; 9494 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9495 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9496 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9497 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9498 if (numFields) { 9499 PetscInt f; 9500 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9501 9502 for (f = 0; f < numFields; f++) { 9503 PetscInt numComp; 9504 9505 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9506 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9507 } 9508 } 9509 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9510 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9511 pStart = PetscMax(pStart,sStart); 9512 pEnd = PetscMin(pEnd,sEnd); 9513 pEnd = PetscMax(pStart,pEnd); 9514 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9515 for (p = pStart; p < pEnd; p++) { 9516 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9517 if (dof) { 9518 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9519 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9520 for (f = 0; f < numFields; f++) { 9521 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9522 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9523 } 9524 } 9525 } 9526 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9527 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9528 PetscFunctionReturn(0); 9529 } 9530 9531 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9532 { 9533 PetscSection aSec; 9534 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9535 const PetscInt *anchors; 9536 PetscInt numFields, f; 9537 IS aIS; 9538 PetscErrorCode ierr; 9539 MatType mtype; 9540 PetscBool iscuda,iskokkos; 9541 9542 PetscFunctionBegin; 9543 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9544 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9545 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9546 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9547 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9548 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9549 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9550 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9551 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9552 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9553 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9554 else mtype = MATSEQAIJ; 9555 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9556 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9557 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9558 /* cSec will be a subset of aSec and section */ 9559 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9560 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9561 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9562 i[0] = 0; 9563 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9564 for (p = pStart; p < pEnd; p++) { 9565 PetscInt rDof, rOff, r; 9566 9567 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9568 if (!rDof) continue; 9569 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9570 if (numFields) { 9571 for (f = 0; f < numFields; f++) { 9572 annz = 0; 9573 for (r = 0; r < rDof; r++) { 9574 a = anchors[rOff + r]; 9575 if (a < sStart || a >= sEnd) continue; 9576 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9577 annz += aDof; 9578 } 9579 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9580 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9581 for (q = 0; q < dof; q++) { 9582 i[off + q + 1] = i[off + q] + annz; 9583 } 9584 } 9585 } else { 9586 annz = 0; 9587 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9588 for (q = 0; q < dof; q++) { 9589 a = anchors[rOff + q]; 9590 if (a < sStart || a >= sEnd) continue; 9591 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9592 annz += aDof; 9593 } 9594 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9595 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9596 for (q = 0; q < dof; q++) { 9597 i[off + q + 1] = i[off + q] + annz; 9598 } 9599 } 9600 } 9601 nnz = i[m]; 9602 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9603 offset = 0; 9604 for (p = pStart; p < pEnd; p++) { 9605 if (numFields) { 9606 for (f = 0; f < numFields; f++) { 9607 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9608 for (q = 0; q < dof; q++) { 9609 PetscInt rDof, rOff, r; 9610 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9611 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9612 for (r = 0; r < rDof; r++) { 9613 PetscInt s; 9614 9615 a = anchors[rOff + r]; 9616 if (a < sStart || a >= sEnd) continue; 9617 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9618 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9619 for (s = 0; s < aDof; s++) { 9620 j[offset++] = aOff + s; 9621 } 9622 } 9623 } 9624 } 9625 } else { 9626 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9627 for (q = 0; q < dof; q++) { 9628 PetscInt rDof, rOff, r; 9629 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9630 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9631 for (r = 0; r < rDof; r++) { 9632 PetscInt s; 9633 9634 a = anchors[rOff + r]; 9635 if (a < sStart || a >= sEnd) continue; 9636 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9637 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9638 for (s = 0; s < aDof; s++) { 9639 j[offset++] = aOff + s; 9640 } 9641 } 9642 } 9643 } 9644 } 9645 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9646 ierr = PetscFree(i);CHKERRQ(ierr); 9647 ierr = PetscFree(j);CHKERRQ(ierr); 9648 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9649 PetscFunctionReturn(0); 9650 } 9651 9652 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9653 { 9654 DM_Plex *plex = (DM_Plex *)dm->data; 9655 PetscSection anchorSection, section, cSec; 9656 Mat cMat; 9657 PetscErrorCode ierr; 9658 9659 PetscFunctionBegin; 9660 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9661 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9662 if (anchorSection) { 9663 PetscInt Nf; 9664 9665 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9666 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9667 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9668 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9669 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9670 ierr = DMSetDefaultConstraints(dm,cSec,cMat,NULL);CHKERRQ(ierr); 9671 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9672 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9673 } 9674 PetscFunctionReturn(0); 9675 } 9676 9677 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9678 { 9679 IS subis; 9680 PetscSection section, subsection; 9681 PetscErrorCode ierr; 9682 9683 PetscFunctionBegin; 9684 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9685 PetscCheckFalse(!section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9686 PetscCheckFalse(!subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9687 /* Create subdomain */ 9688 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9689 /* Create submodel */ 9690 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9691 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9692 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9693 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9694 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9695 /* Create map from submodel to global model */ 9696 if (is) { 9697 PetscSection sectionGlobal, subsectionGlobal; 9698 IS spIS; 9699 const PetscInt *spmap; 9700 PetscInt *subIndices; 9701 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9702 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9703 9704 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9705 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9706 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9707 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9708 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9709 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9710 for (p = pStart; p < pEnd; ++p) { 9711 PetscInt gdof, pSubSize = 0; 9712 9713 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9714 if (gdof > 0) { 9715 for (f = 0; f < Nf; ++f) { 9716 PetscInt fdof, fcdof; 9717 9718 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9719 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9720 pSubSize += fdof-fcdof; 9721 } 9722 subSize += pSubSize; 9723 if (pSubSize) { 9724 if (bs < 0) { 9725 bs = pSubSize; 9726 } else if (bs != pSubSize) { 9727 /* Layout does not admit a pointwise block size */ 9728 bs = 1; 9729 } 9730 } 9731 } 9732 } 9733 /* Must have same blocksize on all procs (some might have no points) */ 9734 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9735 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9736 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9737 else {bs = bsMinMax[0];} 9738 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9739 for (p = pStart; p < pEnd; ++p) { 9740 PetscInt gdof, goff; 9741 9742 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9743 if (gdof > 0) { 9744 const PetscInt point = spmap[p]; 9745 9746 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9747 for (f = 0; f < Nf; ++f) { 9748 PetscInt fdof, fcdof, fc, f2, poff = 0; 9749 9750 /* Can get rid of this loop by storing field information in the global section */ 9751 for (f2 = 0; f2 < f; ++f2) { 9752 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9753 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9754 poff += fdof-fcdof; 9755 } 9756 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9757 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9758 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9759 subIndices[subOff] = goff+poff+fc; 9760 } 9761 } 9762 } 9763 } 9764 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9765 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9766 if (bs > 1) { 9767 /* We need to check that the block size does not come from non-contiguous fields */ 9768 PetscInt i, j, set = 1; 9769 for (i = 0; i < subSize; i += bs) { 9770 for (j = 0; j < bs; ++j) { 9771 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9772 } 9773 } 9774 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9775 } 9776 /* Attach nullspace */ 9777 for (f = 0; f < Nf; ++f) { 9778 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9779 if ((*subdm)->nullspaceConstructors[f]) break; 9780 } 9781 if (f < Nf) { 9782 MatNullSpace nullSpace; 9783 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9784 9785 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9786 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9787 } 9788 } 9789 PetscFunctionReturn(0); 9790 } 9791 9792 /*@ 9793 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9794 9795 Input Parameter: 9796 - dm - The DM 9797 9798 Level: developer 9799 9800 Options Database Keys: 9801 . -dm_plex_monitor_throughput - Activate the monitor 9802 9803 .seealso: DMSetFromOptions(), DMPlexCreate() 9804 @*/ 9805 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9806 { 9807 #if defined(PETSC_USE_LOG) 9808 PetscStageLog stageLog; 9809 PetscLogEvent event; 9810 PetscLogStage stage; 9811 PetscEventPerfInfo eventInfo; 9812 PetscReal cellRate, flopRate; 9813 PetscInt cStart, cEnd, Nf, N; 9814 const char *name; 9815 PetscErrorCode ierr; 9816 #endif 9817 9818 PetscFunctionBegin; 9819 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9820 #if defined(PETSC_USE_LOG) 9821 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9822 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9823 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9824 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9825 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9826 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9827 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9828 N = (cEnd - cStart)*Nf*eventInfo.count; 9829 flopRate = eventInfo.flops/eventInfo.time; 9830 cellRate = N/eventInfo.time; 9831 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); 9832 #else 9833 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9834 #endif 9835 PetscFunctionReturn(0); 9836 } 9837