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);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; /* Just vertices */ 5247 else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 5248 } 5249 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5250 for (PetscInt d=1; d<=dim; d++) { 5251 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5252 PetscInt *perm; 5253 5254 for (f = 0; f < Nf; ++f) { 5255 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5256 size += PetscPowInt(k+1, d)*Nc; 5257 } 5258 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 5259 for (f = 0; f < Nf; ++f) { 5260 switch (d) { 5261 case 1: 5262 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5263 /* 5264 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5265 We want [ vtx0; edge of length k-1; vtx1 ] 5266 */ 5267 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5268 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5269 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5270 foffset = offset; 5271 break; 5272 case 2: 5273 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5274 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5275 /* The SEM order is 5276 5277 v_lb, {e_b}, v_rb, 5278 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5279 v_lt, reverse {e_t}, v_rt 5280 */ 5281 { 5282 const PetscInt of = 0; 5283 const PetscInt oeb = of + PetscSqr(k-1); 5284 const PetscInt oer = oeb + (k-1); 5285 const PetscInt oet = oer + (k-1); 5286 const PetscInt oel = oet + (k-1); 5287 const PetscInt ovlb = oel + (k-1); 5288 const PetscInt ovrb = ovlb + 1; 5289 const PetscInt ovrt = ovrb + 1; 5290 const PetscInt ovlt = ovrt + 1; 5291 PetscInt o; 5292 5293 /* bottom */ 5294 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5295 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5296 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5297 /* middle */ 5298 for (i = 0; i < k-1; ++i) { 5299 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5300 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; 5301 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5302 } 5303 /* top */ 5304 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5305 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5306 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5307 foffset = offset; 5308 } 5309 break; 5310 case 3: 5311 /* The original hex closure is 5312 5313 {c, 5314 f_b, f_t, f_f, f_b, f_r, f_l, 5315 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5316 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5317 */ 5318 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5319 /* The SEM order is 5320 Bottom Slice 5321 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5322 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5323 v_blb, {e_bb}, v_brb, 5324 5325 Middle Slice (j) 5326 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5327 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5328 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5329 5330 Top Slice 5331 v_tlf, {e_tf}, v_trf, 5332 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5333 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5334 */ 5335 { 5336 const PetscInt oc = 0; 5337 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5338 const PetscInt oft = ofb + PetscSqr(k-1); 5339 const PetscInt off = oft + PetscSqr(k-1); 5340 const PetscInt ofk = off + PetscSqr(k-1); 5341 const PetscInt ofr = ofk + PetscSqr(k-1); 5342 const PetscInt ofl = ofr + PetscSqr(k-1); 5343 const PetscInt oebl = ofl + PetscSqr(k-1); 5344 const PetscInt oebb = oebl + (k-1); 5345 const PetscInt oebr = oebb + (k-1); 5346 const PetscInt oebf = oebr + (k-1); 5347 const PetscInt oetf = oebf + (k-1); 5348 const PetscInt oetr = oetf + (k-1); 5349 const PetscInt oetb = oetr + (k-1); 5350 const PetscInt oetl = oetb + (k-1); 5351 const PetscInt oerf = oetl + (k-1); 5352 const PetscInt oelf = oerf + (k-1); 5353 const PetscInt oelb = oelf + (k-1); 5354 const PetscInt oerb = oelb + (k-1); 5355 const PetscInt ovblf = oerb + (k-1); 5356 const PetscInt ovblb = ovblf + 1; 5357 const PetscInt ovbrb = ovblb + 1; 5358 const PetscInt ovbrf = ovbrb + 1; 5359 const PetscInt ovtlf = ovbrf + 1; 5360 const PetscInt ovtrf = ovtlf + 1; 5361 const PetscInt ovtrb = ovtrf + 1; 5362 const PetscInt ovtlb = ovtrb + 1; 5363 PetscInt o, n; 5364 5365 /* Bottom Slice */ 5366 /* bottom */ 5367 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5368 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5369 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5370 /* middle */ 5371 for (i = 0; i < k-1; ++i) { 5372 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5373 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;} 5374 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5375 } 5376 /* top */ 5377 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5378 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5379 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5380 5381 /* Middle Slice */ 5382 for (j = 0; j < k-1; ++j) { 5383 /* bottom */ 5384 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5385 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; 5386 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5387 /* middle */ 5388 for (i = 0; i < k-1; ++i) { 5389 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5390 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; 5391 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5392 } 5393 /* top */ 5394 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5395 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; 5396 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5397 } 5398 5399 /* Top Slice */ 5400 /* bottom */ 5401 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5402 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5403 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5404 /* middle */ 5405 for (i = 0; i < k-1; ++i) { 5406 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5407 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5408 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5409 } 5410 /* top */ 5411 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5412 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5413 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5414 5415 foffset = offset; 5416 } 5417 break; 5418 default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5419 } 5420 } 5421 PetscCheckFalse(offset != size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5422 /* Check permutation */ 5423 { 5424 PetscInt *check; 5425 5426 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5427 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]);} 5428 for (i = 0; i < size; ++i) check[perm[i]] = i; 5429 for (i = 0; i < size; ++i) {PetscCheckFalse(check[i] < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5430 ierr = PetscFree(check);CHKERRQ(ierr); 5431 } 5432 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5433 } 5434 PetscFunctionReturn(0); 5435 } 5436 5437 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5438 { 5439 PetscDS prob; 5440 PetscInt depth, Nf, h; 5441 DMLabel label; 5442 PetscErrorCode ierr; 5443 5444 PetscFunctionBeginHot; 5445 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5446 Nf = prob->Nf; 5447 label = dm->depthLabel; 5448 *dspace = NULL; 5449 if (field < Nf) { 5450 PetscObject disc = prob->disc[field]; 5451 5452 if (disc->classid == PETSCFE_CLASSID) { 5453 PetscDualSpace dsp; 5454 5455 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5456 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5457 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5458 h = depth - 1 - h; 5459 if (h) { 5460 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5461 } else { 5462 *dspace = dsp; 5463 } 5464 } 5465 } 5466 PetscFunctionReturn(0); 5467 } 5468 5469 static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5470 { 5471 PetscScalar *array, *vArray; 5472 const PetscInt *cone, *coneO; 5473 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5474 PetscErrorCode ierr; 5475 5476 PetscFunctionBeginHot; 5477 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5478 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5479 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5480 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5481 if (!values || !*values) { 5482 if ((point >= pStart) && (point < pEnd)) { 5483 PetscInt dof; 5484 5485 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5486 size += dof; 5487 } 5488 for (p = 0; p < numPoints; ++p) { 5489 const PetscInt cp = cone[p]; 5490 PetscInt dof; 5491 5492 if ((cp < pStart) || (cp >= pEnd)) continue; 5493 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5494 size += dof; 5495 } 5496 if (!values) { 5497 if (csize) *csize = size; 5498 PetscFunctionReturn(0); 5499 } 5500 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5501 } else { 5502 array = *values; 5503 } 5504 size = 0; 5505 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5506 if ((point >= pStart) && (point < pEnd)) { 5507 PetscInt dof, off, d; 5508 PetscScalar *varr; 5509 5510 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5511 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5512 varr = &vArray[off]; 5513 for (d = 0; d < dof; ++d, ++offset) { 5514 array[offset] = varr[d]; 5515 } 5516 size += dof; 5517 } 5518 for (p = 0; p < numPoints; ++p) { 5519 const PetscInt cp = cone[p]; 5520 PetscInt o = coneO[p]; 5521 PetscInt dof, off, d; 5522 PetscScalar *varr; 5523 5524 if ((cp < pStart) || (cp >= pEnd)) continue; 5525 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5526 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5527 varr = &vArray[off]; 5528 if (o >= 0) { 5529 for (d = 0; d < dof; ++d, ++offset) { 5530 array[offset] = varr[d]; 5531 } 5532 } else { 5533 for (d = dof-1; d >= 0; --d, ++offset) { 5534 array[offset] = varr[d]; 5535 } 5536 } 5537 size += dof; 5538 } 5539 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5540 if (!*values) { 5541 if (csize) *csize = size; 5542 *values = array; 5543 } else { 5544 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5545 *csize = size; 5546 } 5547 PetscFunctionReturn(0); 5548 } 5549 5550 /* Compress out points not in the section */ 5551 static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5552 { 5553 const PetscInt np = *numPoints; 5554 PetscInt pStart, pEnd, p, q; 5555 PetscErrorCode ierr; 5556 5557 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5558 for (p = 0, q = 0; p < np; ++p) { 5559 const PetscInt r = points[p*2]; 5560 if ((r >= pStart) && (r < pEnd)) { 5561 points[q*2] = r; 5562 points[q*2+1] = points[p*2+1]; 5563 ++q; 5564 } 5565 } 5566 *numPoints = q; 5567 return 0; 5568 } 5569 5570 /* Compressed closure does not apply closure permutation */ 5571 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5572 { 5573 const PetscInt *cla = NULL; 5574 PetscInt np, *pts = NULL; 5575 PetscErrorCode ierr; 5576 5577 PetscFunctionBeginHot; 5578 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5579 if (*clPoints) { 5580 PetscInt dof, off; 5581 5582 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5583 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5584 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5585 np = dof/2; 5586 pts = (PetscInt *) &cla[off]; 5587 } else { 5588 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5589 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5590 } 5591 *numPoints = np; 5592 *points = pts; 5593 *clp = cla; 5594 PetscFunctionReturn(0); 5595 } 5596 5597 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5598 { 5599 PetscErrorCode ierr; 5600 5601 PetscFunctionBeginHot; 5602 if (!*clPoints) { 5603 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5604 } else { 5605 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5606 } 5607 *numPoints = 0; 5608 *points = NULL; 5609 *clSec = NULL; 5610 *clPoints = NULL; 5611 *clp = NULL; 5612 PetscFunctionReturn(0); 5613 } 5614 5615 static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 5616 { 5617 PetscInt offset = 0, p; 5618 const PetscInt **perms = NULL; 5619 const PetscScalar **flips = NULL; 5620 PetscErrorCode ierr; 5621 5622 PetscFunctionBeginHot; 5623 *size = 0; 5624 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5625 for (p = 0; p < numPoints; p++) { 5626 const PetscInt point = points[2*p]; 5627 const PetscInt *perm = perms ? perms[p] : NULL; 5628 const PetscScalar *flip = flips ? flips[p] : NULL; 5629 PetscInt dof, off, d; 5630 const PetscScalar *varr; 5631 5632 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5633 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5634 varr = &vArray[off]; 5635 if (clperm) { 5636 if (perm) { 5637 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5638 } else { 5639 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5640 } 5641 if (flip) { 5642 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5643 } 5644 } else { 5645 if (perm) { 5646 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5647 } else { 5648 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5649 } 5650 if (flip) { 5651 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5652 } 5653 } 5654 offset += dof; 5655 } 5656 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5657 *size = offset; 5658 PetscFunctionReturn(0); 5659 } 5660 5661 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[]) 5662 { 5663 PetscInt offset = 0, f; 5664 PetscErrorCode ierr; 5665 5666 PetscFunctionBeginHot; 5667 *size = 0; 5668 for (f = 0; f < numFields; ++f) { 5669 PetscInt p; 5670 const PetscInt **perms = NULL; 5671 const PetscScalar **flips = NULL; 5672 5673 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5674 for (p = 0; p < numPoints; p++) { 5675 const PetscInt point = points[2*p]; 5676 PetscInt fdof, foff, b; 5677 const PetscScalar *varr; 5678 const PetscInt *perm = perms ? perms[p] : NULL; 5679 const PetscScalar *flip = flips ? flips[p] : NULL; 5680 5681 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5682 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5683 varr = &vArray[foff]; 5684 if (clperm) { 5685 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5686 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5687 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5688 } else { 5689 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5690 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5691 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5692 } 5693 offset += fdof; 5694 } 5695 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5696 } 5697 *size = offset; 5698 PetscFunctionReturn(0); 5699 } 5700 5701 /*@C 5702 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5703 5704 Not collective 5705 5706 Input Parameters: 5707 + dm - The DM 5708 . section - The section describing the layout in v, or NULL to use the default section 5709 . v - The local vector 5710 - point - The point in the DM 5711 5712 Input/Output Parameters: 5713 + csize - The size of the input values array, or NULL; on output the number of values in the closure 5714 - values - An array to use for the values, or NULL to have it allocated automatically; 5715 if the user provided NULL, it is a borrowed array and should not be freed 5716 5717 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5718 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5719 $ assembly function, and a user may already have allocated storage for this operation. 5720 $ 5721 $ A typical use could be 5722 $ 5723 $ values = NULL; 5724 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5725 $ for (cl = 0; cl < clSize; ++cl) { 5726 $ <Compute on closure> 5727 $ } 5728 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5729 $ 5730 $ or 5731 $ 5732 $ PetscMalloc1(clMaxSize, &values); 5733 $ for (p = pStart; p < pEnd; ++p) { 5734 $ clSize = clMaxSize; 5735 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5736 $ for (cl = 0; cl < clSize; ++cl) { 5737 $ <Compute on closure> 5738 $ } 5739 $ } 5740 $ PetscFree(values); 5741 5742 Fortran Notes: 5743 Since it returns an array, this routine is only available in Fortran 90, and you must 5744 include petsc.h90 in your code. 5745 5746 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5747 5748 Level: intermediate 5749 5750 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5751 @*/ 5752 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5753 { 5754 PetscSection clSection; 5755 IS clPoints; 5756 PetscInt *points = NULL; 5757 const PetscInt *clp, *perm; 5758 PetscInt depth, numFields, numPoints, asize; 5759 PetscErrorCode ierr; 5760 5761 PetscFunctionBeginHot; 5762 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5763 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5764 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5765 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5766 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5767 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5768 if (depth == 1 && numFields < 2) { 5769 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5770 PetscFunctionReturn(0); 5771 } 5772 /* Get points */ 5773 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5774 /* Get sizes */ 5775 asize = 0; 5776 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5777 PetscInt dof; 5778 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5779 asize += dof; 5780 } 5781 if (values) { 5782 const PetscScalar *vArray; 5783 PetscInt size; 5784 5785 if (*values) { 5786 PetscCheckFalse(*csize < asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize); 5787 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5788 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5789 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5790 /* Get values */ 5791 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5792 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5793 PetscCheckFalse(asize != size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5794 /* Cleanup array */ 5795 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5796 } 5797 if (csize) *csize = asize; 5798 /* Cleanup points */ 5799 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5800 PetscFunctionReturn(0); 5801 } 5802 5803 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5804 { 5805 DMLabel depthLabel; 5806 PetscSection clSection; 5807 IS clPoints; 5808 PetscScalar *array; 5809 const PetscScalar *vArray; 5810 PetscInt *points = NULL; 5811 const PetscInt *clp, *perm = NULL; 5812 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5813 PetscErrorCode ierr; 5814 5815 PetscFunctionBeginHot; 5816 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5817 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5818 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5819 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5820 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5821 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5822 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5823 if (mdepth == 1 && numFields < 2) { 5824 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5825 PetscFunctionReturn(0); 5826 } 5827 /* Get points */ 5828 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5829 for (clsize=0,p=0; p<Np; p++) { 5830 PetscInt dof; 5831 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5832 clsize += dof; 5833 } 5834 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5835 /* Filter points */ 5836 for (p = 0; p < numPoints*2; p += 2) { 5837 PetscInt dep; 5838 5839 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5840 if (dep != depth) continue; 5841 points[Np*2+0] = points[p]; 5842 points[Np*2+1] = points[p+1]; 5843 ++Np; 5844 } 5845 /* Get array */ 5846 if (!values || !*values) { 5847 PetscInt asize = 0, dof; 5848 5849 for (p = 0; p < Np*2; p += 2) { 5850 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5851 asize += dof; 5852 } 5853 if (!values) { 5854 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5855 if (csize) *csize = asize; 5856 PetscFunctionReturn(0); 5857 } 5858 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5859 } else { 5860 array = *values; 5861 } 5862 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5863 /* Get values */ 5864 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5865 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5866 /* Cleanup points */ 5867 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5868 /* Cleanup array */ 5869 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5870 if (!*values) { 5871 if (csize) *csize = size; 5872 *values = array; 5873 } else { 5874 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5875 *csize = size; 5876 } 5877 PetscFunctionReturn(0); 5878 } 5879 5880 /*@C 5881 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5882 5883 Not collective 5884 5885 Input Parameters: 5886 + dm - The DM 5887 . section - The section describing the layout in v, or NULL to use the default section 5888 . v - The local vector 5889 . point - The point in the DM 5890 . csize - The number of values in the closure, or NULL 5891 - values - The array of values, which is a borrowed array and should not be freed 5892 5893 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5894 5895 Fortran Notes: 5896 Since it returns an array, this routine is only available in Fortran 90, and you must 5897 include petsc.h90 in your code. 5898 5899 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5900 5901 Level: intermediate 5902 5903 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5904 @*/ 5905 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5906 { 5907 PetscInt size = 0; 5908 PetscErrorCode ierr; 5909 5910 PetscFunctionBegin; 5911 /* Should work without recalculating size */ 5912 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5913 *values = NULL; 5914 PetscFunctionReturn(0); 5915 } 5916 5917 static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 5918 static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5919 5920 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[]) 5921 { 5922 PetscInt cdof; /* The number of constraints on this point */ 5923 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5924 PetscScalar *a; 5925 PetscInt off, cind = 0, k; 5926 PetscErrorCode ierr; 5927 5928 PetscFunctionBegin; 5929 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5930 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5931 a = &array[off]; 5932 if (!cdof || setBC) { 5933 if (clperm) { 5934 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5935 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5936 } else { 5937 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5938 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5939 } 5940 } else { 5941 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5942 if (clperm) { 5943 if (perm) {for (k = 0; k < dof; ++k) { 5944 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5945 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5946 } 5947 } else { 5948 for (k = 0; k < dof; ++k) { 5949 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5950 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5951 } 5952 } 5953 } else { 5954 if (perm) { 5955 for (k = 0; k < dof; ++k) { 5956 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5957 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5958 } 5959 } else { 5960 for (k = 0; k < dof; ++k) { 5961 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5962 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5963 } 5964 } 5965 } 5966 } 5967 PetscFunctionReturn(0); 5968 } 5969 5970 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[]) 5971 { 5972 PetscInt cdof; /* The number of constraints on this point */ 5973 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5974 PetscScalar *a; 5975 PetscInt off, cind = 0, k; 5976 PetscErrorCode ierr; 5977 5978 PetscFunctionBegin; 5979 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5980 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5981 a = &array[off]; 5982 if (cdof) { 5983 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5984 if (clperm) { 5985 if (perm) { 5986 for (k = 0; k < dof; ++k) { 5987 if ((cind < cdof) && (k == cdofs[cind])) { 5988 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5989 cind++; 5990 } 5991 } 5992 } else { 5993 for (k = 0; k < dof; ++k) { 5994 if ((cind < cdof) && (k == cdofs[cind])) { 5995 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5996 cind++; 5997 } 5998 } 5999 } 6000 } else { 6001 if (perm) { 6002 for (k = 0; k < dof; ++k) { 6003 if ((cind < cdof) && (k == cdofs[cind])) { 6004 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 6005 cind++; 6006 } 6007 } 6008 } else { 6009 for (k = 0; k < dof; ++k) { 6010 if ((cind < cdof) && (k == cdofs[cind])) { 6011 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 6012 cind++; 6013 } 6014 } 6015 } 6016 } 6017 } 6018 PetscFunctionReturn(0); 6019 } 6020 6021 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[]) 6022 { 6023 PetscScalar *a; 6024 PetscInt fdof, foff, fcdof, foffset = *offset; 6025 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6026 PetscInt cind = 0, b; 6027 PetscErrorCode ierr; 6028 6029 PetscFunctionBegin; 6030 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6031 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6032 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6033 a = &array[foff]; 6034 if (!fcdof || setBC) { 6035 if (clperm) { 6036 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 6037 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6038 } else { 6039 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 6040 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6041 } 6042 } else { 6043 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6044 if (clperm) { 6045 if (perm) { 6046 for (b = 0; b < fdof; b++) { 6047 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6048 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6049 } 6050 } else { 6051 for (b = 0; b < fdof; b++) { 6052 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6053 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6054 } 6055 } 6056 } else { 6057 if (perm) { 6058 for (b = 0; b < fdof; b++) { 6059 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6060 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6061 } 6062 } else { 6063 for (b = 0; b < fdof; b++) { 6064 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6065 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6066 } 6067 } 6068 } 6069 } 6070 *offset += fdof; 6071 PetscFunctionReturn(0); 6072 } 6073 6074 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[]) 6075 { 6076 PetscScalar *a; 6077 PetscInt fdof, foff, fcdof, foffset = *offset; 6078 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6079 PetscInt Nc, cind = 0, ncind = 0, b; 6080 PetscBool ncSet, fcSet; 6081 PetscErrorCode ierr; 6082 6083 PetscFunctionBegin; 6084 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 6085 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6086 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6087 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6088 a = &array[foff]; 6089 if (fcdof) { 6090 /* We just override fcdof and fcdofs with Ncc and comps */ 6091 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6092 if (clperm) { 6093 if (perm) { 6094 if (comps) { 6095 for (b = 0; b < fdof; b++) { 6096 ncSet = fcSet = PETSC_FALSE; 6097 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6098 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6099 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6100 } 6101 } else { 6102 for (b = 0; b < fdof; b++) { 6103 if ((cind < fcdof) && (b == fcdofs[cind])) { 6104 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6105 ++cind; 6106 } 6107 } 6108 } 6109 } else { 6110 if (comps) { 6111 for (b = 0; b < fdof; b++) { 6112 ncSet = fcSet = PETSC_FALSE; 6113 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6114 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6115 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6116 } 6117 } else { 6118 for (b = 0; b < fdof; b++) { 6119 if ((cind < fcdof) && (b == fcdofs[cind])) { 6120 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6121 ++cind; 6122 } 6123 } 6124 } 6125 } 6126 } else { 6127 if (perm) { 6128 if (comps) { 6129 for (b = 0; b < fdof; b++) { 6130 ncSet = fcSet = PETSC_FALSE; 6131 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6132 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6133 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6134 } 6135 } else { 6136 for (b = 0; b < fdof; b++) { 6137 if ((cind < fcdof) && (b == fcdofs[cind])) { 6138 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6139 ++cind; 6140 } 6141 } 6142 } 6143 } else { 6144 if (comps) { 6145 for (b = 0; b < fdof; b++) { 6146 ncSet = fcSet = PETSC_FALSE; 6147 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6148 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6149 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6150 } 6151 } else { 6152 for (b = 0; b < fdof; b++) { 6153 if ((cind < fcdof) && (b == fcdofs[cind])) { 6154 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6155 ++cind; 6156 } 6157 } 6158 } 6159 } 6160 } 6161 } 6162 *offset += fdof; 6163 PetscFunctionReturn(0); 6164 } 6165 6166 static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6167 { 6168 PetscScalar *array; 6169 const PetscInt *cone, *coneO; 6170 PetscInt pStart, pEnd, p, numPoints, off, dof; 6171 PetscErrorCode ierr; 6172 6173 PetscFunctionBeginHot; 6174 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6175 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6176 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6177 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6178 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6179 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6180 const PetscInt cp = !p ? point : cone[p-1]; 6181 const PetscInt o = !p ? 0 : coneO[p-1]; 6182 6183 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 6184 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6185 /* ADD_VALUES */ 6186 { 6187 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6188 PetscScalar *a; 6189 PetscInt cdof, coff, cind = 0, k; 6190 6191 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 6192 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 6193 a = &array[coff]; 6194 if (!cdof) { 6195 if (o >= 0) { 6196 for (k = 0; k < dof; ++k) { 6197 a[k] += values[off+k]; 6198 } 6199 } else { 6200 for (k = 0; k < dof; ++k) { 6201 a[k] += values[off+dof-k-1]; 6202 } 6203 } 6204 } else { 6205 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6206 if (o >= 0) { 6207 for (k = 0; k < dof; ++k) { 6208 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6209 a[k] += values[off+k]; 6210 } 6211 } else { 6212 for (k = 0; k < dof; ++k) { 6213 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6214 a[k] += values[off+dof-k-1]; 6215 } 6216 } 6217 } 6218 } 6219 } 6220 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6221 PetscFunctionReturn(0); 6222 } 6223 6224 /*@C 6225 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6226 6227 Not collective 6228 6229 Input Parameters: 6230 + dm - The DM 6231 . section - The section describing the layout in v, or NULL to use the default section 6232 . v - The local vector 6233 . point - The point in the DM 6234 . values - The array of values 6235 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6236 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6237 6238 Fortran Notes: 6239 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6240 6241 Level: intermediate 6242 6243 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6244 @*/ 6245 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6246 { 6247 PetscSection clSection; 6248 IS clPoints; 6249 PetscScalar *array; 6250 PetscInt *points = NULL; 6251 const PetscInt *clp, *clperm = NULL; 6252 PetscInt depth, numFields, numPoints, p, clsize; 6253 PetscErrorCode ierr; 6254 6255 PetscFunctionBeginHot; 6256 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6257 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6258 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6259 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6260 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6261 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6262 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6263 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6264 PetscFunctionReturn(0); 6265 } 6266 /* Get points */ 6267 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6268 for (clsize=0,p=0; p<numPoints; p++) { 6269 PetscInt dof; 6270 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6271 clsize += dof; 6272 } 6273 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6274 /* Get array */ 6275 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6276 /* Get values */ 6277 if (numFields > 0) { 6278 PetscInt offset = 0, f; 6279 for (f = 0; f < numFields; ++f) { 6280 const PetscInt **perms = NULL; 6281 const PetscScalar **flips = NULL; 6282 6283 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6284 switch (mode) { 6285 case INSERT_VALUES: 6286 for (p = 0; p < numPoints; p++) { 6287 const PetscInt point = points[2*p]; 6288 const PetscInt *perm = perms ? perms[p] : NULL; 6289 const PetscScalar *flip = flips ? flips[p] : NULL; 6290 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6291 } break; 6292 case INSERT_ALL_VALUES: 6293 for (p = 0; p < numPoints; p++) { 6294 const PetscInt point = points[2*p]; 6295 const PetscInt *perm = perms ? perms[p] : NULL; 6296 const PetscScalar *flip = flips ? flips[p] : NULL; 6297 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6298 } break; 6299 case INSERT_BC_VALUES: 6300 for (p = 0; p < numPoints; p++) { 6301 const PetscInt point = points[2*p]; 6302 const PetscInt *perm = perms ? perms[p] : NULL; 6303 const PetscScalar *flip = flips ? flips[p] : NULL; 6304 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6305 } break; 6306 case ADD_VALUES: 6307 for (p = 0; p < numPoints; p++) { 6308 const PetscInt point = points[2*p]; 6309 const PetscInt *perm = perms ? perms[p] : NULL; 6310 const PetscScalar *flip = flips ? flips[p] : NULL; 6311 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6312 } break; 6313 case ADD_ALL_VALUES: 6314 for (p = 0; p < numPoints; p++) { 6315 const PetscInt point = points[2*p]; 6316 const PetscInt *perm = perms ? perms[p] : NULL; 6317 const PetscScalar *flip = flips ? flips[p] : NULL; 6318 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6319 } break; 6320 case ADD_BC_VALUES: 6321 for (p = 0; p < numPoints; p++) { 6322 const PetscInt point = points[2*p]; 6323 const PetscInt *perm = perms ? perms[p] : NULL; 6324 const PetscScalar *flip = flips ? flips[p] : NULL; 6325 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6326 } break; 6327 default: 6328 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6329 } 6330 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6331 } 6332 } else { 6333 PetscInt dof, off; 6334 const PetscInt **perms = NULL; 6335 const PetscScalar **flips = NULL; 6336 6337 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6338 switch (mode) { 6339 case INSERT_VALUES: 6340 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6341 const PetscInt point = points[2*p]; 6342 const PetscInt *perm = perms ? perms[p] : NULL; 6343 const PetscScalar *flip = flips ? flips[p] : NULL; 6344 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6345 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6346 } break; 6347 case INSERT_ALL_VALUES: 6348 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6349 const PetscInt point = points[2*p]; 6350 const PetscInt *perm = perms ? perms[p] : NULL; 6351 const PetscScalar *flip = flips ? flips[p] : NULL; 6352 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6353 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6354 } break; 6355 case INSERT_BC_VALUES: 6356 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6357 const PetscInt point = points[2*p]; 6358 const PetscInt *perm = perms ? perms[p] : NULL; 6359 const PetscScalar *flip = flips ? flips[p] : NULL; 6360 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6361 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6362 } break; 6363 case ADD_VALUES: 6364 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6365 const PetscInt point = points[2*p]; 6366 const PetscInt *perm = perms ? perms[p] : NULL; 6367 const PetscScalar *flip = flips ? flips[p] : NULL; 6368 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6369 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6370 } break; 6371 case ADD_ALL_VALUES: 6372 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6373 const PetscInt point = points[2*p]; 6374 const PetscInt *perm = perms ? perms[p] : NULL; 6375 const PetscScalar *flip = flips ? flips[p] : NULL; 6376 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6377 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6378 } break; 6379 case ADD_BC_VALUES: 6380 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6381 const PetscInt point = points[2*p]; 6382 const PetscInt *perm = perms ? perms[p] : NULL; 6383 const PetscScalar *flip = flips ? flips[p] : NULL; 6384 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6385 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6386 } break; 6387 default: 6388 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6389 } 6390 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6391 } 6392 /* Cleanup points */ 6393 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6394 /* Cleanup array */ 6395 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6396 PetscFunctionReturn(0); 6397 } 6398 6399 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6400 static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6401 { 6402 PetscFunctionBegin; 6403 if (label) { 6404 PetscInt val, fdof; 6405 PetscErrorCode ierr; 6406 6407 /* There is a problem with this: 6408 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6409 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6410 Thus I am only going to check val != -1, not val != labelId 6411 */ 6412 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6413 if (val < 0) { 6414 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6415 *offset += fdof; 6416 PetscFunctionReturn(1); 6417 } 6418 } 6419 PetscFunctionReturn(0); 6420 } 6421 6422 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6423 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) 6424 { 6425 PetscSection clSection; 6426 IS clPoints; 6427 PetscScalar *array; 6428 PetscInt *points = NULL; 6429 const PetscInt *clp; 6430 PetscInt numFields, numPoints, p; 6431 PetscInt offset = 0, f; 6432 PetscErrorCode ierr; 6433 6434 PetscFunctionBeginHot; 6435 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6436 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6437 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6438 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6439 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6440 /* Get points */ 6441 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6442 /* Get array */ 6443 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6444 /* Get values */ 6445 for (f = 0; f < numFields; ++f) { 6446 const PetscInt **perms = NULL; 6447 const PetscScalar **flips = NULL; 6448 6449 if (!fieldActive[f]) { 6450 for (p = 0; p < numPoints*2; p += 2) { 6451 PetscInt fdof; 6452 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6453 offset += fdof; 6454 } 6455 continue; 6456 } 6457 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6458 switch (mode) { 6459 case INSERT_VALUES: 6460 for (p = 0; p < numPoints; p++) { 6461 const PetscInt point = points[2*p]; 6462 const PetscInt *perm = perms ? perms[p] : NULL; 6463 const PetscScalar *flip = flips ? flips[p] : NULL; 6464 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6465 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6466 } break; 6467 case INSERT_ALL_VALUES: 6468 for (p = 0; p < numPoints; p++) { 6469 const PetscInt point = points[2*p]; 6470 const PetscInt *perm = perms ? perms[p] : NULL; 6471 const PetscScalar *flip = flips ? flips[p] : NULL; 6472 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6473 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6474 } break; 6475 case INSERT_BC_VALUES: 6476 for (p = 0; p < numPoints; p++) { 6477 const PetscInt point = points[2*p]; 6478 const PetscInt *perm = perms ? perms[p] : NULL; 6479 const PetscScalar *flip = flips ? flips[p] : NULL; 6480 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6481 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6482 } break; 6483 case ADD_VALUES: 6484 for (p = 0; p < numPoints; p++) { 6485 const PetscInt point = points[2*p]; 6486 const PetscInt *perm = perms ? perms[p] : NULL; 6487 const PetscScalar *flip = flips ? flips[p] : NULL; 6488 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6489 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6490 } break; 6491 case ADD_ALL_VALUES: 6492 for (p = 0; p < numPoints; p++) { 6493 const PetscInt point = points[2*p]; 6494 const PetscInt *perm = perms ? perms[p] : NULL; 6495 const PetscScalar *flip = flips ? flips[p] : NULL; 6496 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6497 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6498 } break; 6499 default: 6500 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6501 } 6502 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6503 } 6504 /* Cleanup points */ 6505 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6506 /* Cleanup array */ 6507 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6508 PetscFunctionReturn(0); 6509 } 6510 6511 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6512 { 6513 PetscMPIInt rank; 6514 PetscInt i, j; 6515 PetscErrorCode ierr; 6516 6517 PetscFunctionBegin; 6518 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6519 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6520 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6521 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6522 numCIndices = numCIndices ? numCIndices : numRIndices; 6523 if (!values) PetscFunctionReturn(0); 6524 for (i = 0; i < numRIndices; i++) { 6525 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6526 for (j = 0; j < numCIndices; j++) { 6527 #if defined(PETSC_USE_COMPLEX) 6528 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6529 #else 6530 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6531 #endif 6532 } 6533 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6534 } 6535 PetscFunctionReturn(0); 6536 } 6537 6538 /* 6539 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6540 6541 Input Parameters: 6542 + section - The section for this data layout 6543 . islocal - Is the section (and thus indices being requested) local or global? 6544 . point - The point contributing dofs with these indices 6545 . off - The global offset of this point 6546 . loff - The local offset of each field 6547 . setBC - The flag determining whether to include indices of boundary values 6548 . perm - A permutation of the dofs on this point, or NULL 6549 - indperm - A permutation of the entire indices array, or NULL 6550 6551 Output Parameter: 6552 . indices - Indices for dofs on this point 6553 6554 Level: developer 6555 6556 Note: The indices could be local or global, depending on the value of 'off'. 6557 */ 6558 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6559 { 6560 PetscInt dof; /* The number of unknowns on this point */ 6561 PetscInt cdof; /* The number of constraints on this point */ 6562 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6563 PetscInt cind = 0, k; 6564 PetscErrorCode ierr; 6565 6566 PetscFunctionBegin; 6567 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6568 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6569 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6570 if (!cdof || setBC) { 6571 for (k = 0; k < dof; ++k) { 6572 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6573 const PetscInt ind = indperm ? indperm[preind] : preind; 6574 6575 indices[ind] = off + k; 6576 } 6577 } else { 6578 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6579 for (k = 0; k < dof; ++k) { 6580 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6581 const PetscInt ind = indperm ? indperm[preind] : preind; 6582 6583 if ((cind < cdof) && (k == cdofs[cind])) { 6584 /* Insert check for returning constrained indices */ 6585 indices[ind] = -(off+k+1); 6586 ++cind; 6587 } else { 6588 indices[ind] = off + k - (islocal ? 0 : cind); 6589 } 6590 } 6591 } 6592 *loff += dof; 6593 PetscFunctionReturn(0); 6594 } 6595 6596 /* 6597 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6598 6599 Input Parameters: 6600 + section - a section (global or local) 6601 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6602 . point - point within section 6603 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6604 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6605 . setBC - identify constrained (boundary condition) points via involution. 6606 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6607 . permsoff - offset 6608 - indperm - index permutation 6609 6610 Output Parameter: 6611 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6612 . indices - array to hold indices (as defined by section) of each dof associated with point 6613 6614 Notes: 6615 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6616 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6617 in the local vector. 6618 6619 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6620 significant). It is invalid to call with a global section and setBC=true. 6621 6622 Developer Note: 6623 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6624 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6625 offset could be obtained from the section instead of passing it explicitly as we do now. 6626 6627 Example: 6628 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6629 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6630 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6631 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. 6632 6633 Level: developer 6634 */ 6635 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[]) 6636 { 6637 PetscInt numFields, foff, f; 6638 PetscErrorCode ierr; 6639 6640 PetscFunctionBegin; 6641 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6642 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6643 for (f = 0, foff = 0; f < numFields; ++f) { 6644 PetscInt fdof, cfdof; 6645 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6646 PetscInt cind = 0, b; 6647 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6648 6649 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6650 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6651 if (!cfdof || setBC) { 6652 for (b = 0; b < fdof; ++b) { 6653 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6654 const PetscInt ind = indperm ? indperm[preind] : preind; 6655 6656 indices[ind] = off+foff+b; 6657 } 6658 } else { 6659 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6660 for (b = 0; b < fdof; ++b) { 6661 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6662 const PetscInt ind = indperm ? indperm[preind] : preind; 6663 6664 if ((cind < cfdof) && (b == fcdofs[cind])) { 6665 indices[ind] = -(off+foff+b+1); 6666 ++cind; 6667 } else { 6668 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6669 } 6670 } 6671 } 6672 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6673 foffs[f] += fdof; 6674 } 6675 PetscFunctionReturn(0); 6676 } 6677 6678 /* 6679 This version believes the globalSection offsets for each field, rather than just the point offset 6680 6681 . foffs - The offset into 'indices' for each field, since it is segregated by field 6682 6683 Notes: 6684 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6685 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6686 */ 6687 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6688 { 6689 PetscInt numFields, foff, f; 6690 PetscErrorCode ierr; 6691 6692 PetscFunctionBegin; 6693 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6694 for (f = 0; f < numFields; ++f) { 6695 PetscInt fdof, cfdof; 6696 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6697 PetscInt cind = 0, b; 6698 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6699 6700 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6701 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6702 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6703 if (!cfdof) { 6704 for (b = 0; b < fdof; ++b) { 6705 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6706 const PetscInt ind = indperm ? indperm[preind] : preind; 6707 6708 indices[ind] = foff+b; 6709 } 6710 } else { 6711 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6712 for (b = 0; b < fdof; ++b) { 6713 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6714 const PetscInt ind = indperm ? indperm[preind] : preind; 6715 6716 if ((cind < cfdof) && (b == fcdofs[cind])) { 6717 indices[ind] = -(foff+b+1); 6718 ++cind; 6719 } else { 6720 indices[ind] = foff+b-cind; 6721 } 6722 } 6723 } 6724 foffs[f] += fdof; 6725 } 6726 PetscFunctionReturn(0); 6727 } 6728 6729 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) 6730 { 6731 Mat cMat; 6732 PetscSection aSec, cSec; 6733 IS aIS; 6734 PetscInt aStart = -1, aEnd = -1; 6735 const PetscInt *anchors; 6736 PetscInt numFields, f, p, q, newP = 0; 6737 PetscInt newNumPoints = 0, newNumIndices = 0; 6738 PetscInt *newPoints, *indices, *newIndices; 6739 PetscInt maxAnchor, maxDof; 6740 PetscInt newOffsets[32]; 6741 PetscInt *pointMatOffsets[32]; 6742 PetscInt *newPointOffsets[32]; 6743 PetscScalar *pointMat[32]; 6744 PetscScalar *newValues=NULL,*tmpValues; 6745 PetscBool anyConstrained = PETSC_FALSE; 6746 PetscErrorCode ierr; 6747 6748 PetscFunctionBegin; 6749 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6750 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6751 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6752 6753 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6754 /* if there are point-to-point constraints */ 6755 if (aSec) { 6756 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6757 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6758 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6759 /* figure out how many points are going to be in the new element matrix 6760 * (we allow double counting, because it's all just going to be summed 6761 * into the global matrix anyway) */ 6762 for (p = 0; p < 2*numPoints; p+=2) { 6763 PetscInt b = points[p]; 6764 PetscInt bDof = 0, bSecDof; 6765 6766 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6767 if (!bSecDof) { 6768 continue; 6769 } 6770 if (b >= aStart && b < aEnd) { 6771 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6772 } 6773 if (bDof) { 6774 /* this point is constrained */ 6775 /* it is going to be replaced by its anchors */ 6776 PetscInt bOff, q; 6777 6778 anyConstrained = PETSC_TRUE; 6779 newNumPoints += bDof; 6780 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6781 for (q = 0; q < bDof; q++) { 6782 PetscInt a = anchors[bOff + q]; 6783 PetscInt aDof; 6784 6785 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6786 newNumIndices += aDof; 6787 for (f = 0; f < numFields; ++f) { 6788 PetscInt fDof; 6789 6790 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6791 newOffsets[f+1] += fDof; 6792 } 6793 } 6794 } 6795 else { 6796 /* this point is not constrained */ 6797 newNumPoints++; 6798 newNumIndices += bSecDof; 6799 for (f = 0; f < numFields; ++f) { 6800 PetscInt fDof; 6801 6802 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6803 newOffsets[f+1] += fDof; 6804 } 6805 } 6806 } 6807 } 6808 if (!anyConstrained) { 6809 if (outNumPoints) *outNumPoints = 0; 6810 if (outNumIndices) *outNumIndices = 0; 6811 if (outPoints) *outPoints = NULL; 6812 if (outValues) *outValues = NULL; 6813 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6814 PetscFunctionReturn(0); 6815 } 6816 6817 if (outNumPoints) *outNumPoints = newNumPoints; 6818 if (outNumIndices) *outNumIndices = newNumIndices; 6819 6820 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6821 6822 if (!outPoints && !outValues) { 6823 if (offsets) { 6824 for (f = 0; f <= numFields; f++) { 6825 offsets[f] = newOffsets[f]; 6826 } 6827 } 6828 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6829 PetscFunctionReturn(0); 6830 } 6831 6832 PetscCheckFalse(numFields && newOffsets[numFields] != newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6833 6834 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 6835 6836 /* workspaces */ 6837 if (numFields) { 6838 for (f = 0; f < numFields; f++) { 6839 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6840 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6841 } 6842 } 6843 else { 6844 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6845 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6846 } 6847 6848 /* get workspaces for the point-to-point matrices */ 6849 if (numFields) { 6850 PetscInt totalOffset, totalMatOffset; 6851 6852 for (p = 0; p < numPoints; p++) { 6853 PetscInt b = points[2*p]; 6854 PetscInt bDof = 0, bSecDof; 6855 6856 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6857 if (!bSecDof) { 6858 for (f = 0; f < numFields; f++) { 6859 newPointOffsets[f][p + 1] = 0; 6860 pointMatOffsets[f][p + 1] = 0; 6861 } 6862 continue; 6863 } 6864 if (b >= aStart && b < aEnd) { 6865 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6866 } 6867 if (bDof) { 6868 for (f = 0; f < numFields; f++) { 6869 PetscInt fDof, q, bOff, allFDof = 0; 6870 6871 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6872 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6873 for (q = 0; q < bDof; q++) { 6874 PetscInt a = anchors[bOff + q]; 6875 PetscInt aFDof; 6876 6877 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6878 allFDof += aFDof; 6879 } 6880 newPointOffsets[f][p+1] = allFDof; 6881 pointMatOffsets[f][p+1] = fDof * allFDof; 6882 } 6883 } 6884 else { 6885 for (f = 0; f < numFields; f++) { 6886 PetscInt fDof; 6887 6888 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6889 newPointOffsets[f][p+1] = fDof; 6890 pointMatOffsets[f][p+1] = 0; 6891 } 6892 } 6893 } 6894 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6895 newPointOffsets[f][0] = totalOffset; 6896 pointMatOffsets[f][0] = totalMatOffset; 6897 for (p = 0; p < numPoints; p++) { 6898 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6899 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6900 } 6901 totalOffset = newPointOffsets[f][numPoints]; 6902 totalMatOffset = pointMatOffsets[f][numPoints]; 6903 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6904 } 6905 } 6906 else { 6907 for (p = 0; p < numPoints; p++) { 6908 PetscInt b = points[2*p]; 6909 PetscInt bDof = 0, bSecDof; 6910 6911 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6912 if (!bSecDof) { 6913 newPointOffsets[0][p + 1] = 0; 6914 pointMatOffsets[0][p + 1] = 0; 6915 continue; 6916 } 6917 if (b >= aStart && b < aEnd) { 6918 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6919 } 6920 if (bDof) { 6921 PetscInt bOff, q, allDof = 0; 6922 6923 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6924 for (q = 0; q < bDof; q++) { 6925 PetscInt a = anchors[bOff + q], aDof; 6926 6927 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6928 allDof += aDof; 6929 } 6930 newPointOffsets[0][p+1] = allDof; 6931 pointMatOffsets[0][p+1] = bSecDof * allDof; 6932 } 6933 else { 6934 newPointOffsets[0][p+1] = bSecDof; 6935 pointMatOffsets[0][p+1] = 0; 6936 } 6937 } 6938 newPointOffsets[0][0] = 0; 6939 pointMatOffsets[0][0] = 0; 6940 for (p = 0; p < numPoints; p++) { 6941 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6942 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6943 } 6944 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6945 } 6946 6947 /* output arrays */ 6948 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6949 6950 /* get the point-to-point matrices; construct newPoints */ 6951 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6952 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6953 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6954 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6955 if (numFields) { 6956 for (p = 0, newP = 0; p < numPoints; p++) { 6957 PetscInt b = points[2*p]; 6958 PetscInt o = points[2*p+1]; 6959 PetscInt bDof = 0, bSecDof; 6960 6961 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6962 if (!bSecDof) { 6963 continue; 6964 } 6965 if (b >= aStart && b < aEnd) { 6966 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6967 } 6968 if (bDof) { 6969 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6970 6971 fStart[0] = 0; 6972 fEnd[0] = 0; 6973 for (f = 0; f < numFields; f++) { 6974 PetscInt fDof; 6975 6976 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6977 fStart[f+1] = fStart[f] + fDof; 6978 fEnd[f+1] = fStart[f+1]; 6979 } 6980 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6981 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6982 6983 fAnchorStart[0] = 0; 6984 fAnchorEnd[0] = 0; 6985 for (f = 0; f < numFields; f++) { 6986 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6987 6988 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6989 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6990 } 6991 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6992 for (q = 0; q < bDof; q++) { 6993 PetscInt a = anchors[bOff + q], aOff; 6994 6995 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6996 newPoints[2*(newP + q)] = a; 6997 newPoints[2*(newP + q) + 1] = 0; 6998 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6999 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 7000 } 7001 newP += bDof; 7002 7003 if (outValues) { 7004 /* get the point-to-point submatrix */ 7005 for (f = 0; f < numFields; f++) { 7006 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 7007 } 7008 } 7009 } 7010 else { 7011 newPoints[2 * newP] = b; 7012 newPoints[2 * newP + 1] = o; 7013 newP++; 7014 } 7015 } 7016 } else { 7017 for (p = 0; p < numPoints; p++) { 7018 PetscInt b = points[2*p]; 7019 PetscInt o = points[2*p+1]; 7020 PetscInt bDof = 0, bSecDof; 7021 7022 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 7023 if (!bSecDof) { 7024 continue; 7025 } 7026 if (b >= aStart && b < aEnd) { 7027 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 7028 } 7029 if (bDof) { 7030 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7031 7032 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 7033 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 7034 7035 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 7036 for (q = 0; q < bDof; q++) { 7037 PetscInt a = anchors[bOff + q], aOff; 7038 7039 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7040 7041 newPoints[2*(newP + q)] = a; 7042 newPoints[2*(newP + q) + 1] = 0; 7043 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7044 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 7045 } 7046 newP += bDof; 7047 7048 /* get the point-to-point submatrix */ 7049 if (outValues) { 7050 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 7051 } 7052 } 7053 else { 7054 newPoints[2 * newP] = b; 7055 newPoints[2 * newP + 1] = o; 7056 newP++; 7057 } 7058 } 7059 } 7060 7061 if (outValues) { 7062 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7063 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 7064 /* multiply constraints on the right */ 7065 if (numFields) { 7066 for (f = 0; f < numFields; f++) { 7067 PetscInt oldOff = offsets[f]; 7068 7069 for (p = 0; p < numPoints; p++) { 7070 PetscInt cStart = newPointOffsets[f][p]; 7071 PetscInt b = points[2 * p]; 7072 PetscInt c, r, k; 7073 PetscInt dof; 7074 7075 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7076 if (!dof) { 7077 continue; 7078 } 7079 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7080 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7081 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7082 7083 for (r = 0; r < numIndices; r++) { 7084 for (c = 0; c < nCols; c++) { 7085 for (k = 0; k < dof; k++) { 7086 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7087 } 7088 } 7089 } 7090 } 7091 else { 7092 /* copy this column as is */ 7093 for (r = 0; r < numIndices; r++) { 7094 for (c = 0; c < dof; c++) { 7095 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7096 } 7097 } 7098 } 7099 oldOff += dof; 7100 } 7101 } 7102 } 7103 else { 7104 PetscInt oldOff = 0; 7105 for (p = 0; p < numPoints; p++) { 7106 PetscInt cStart = newPointOffsets[0][p]; 7107 PetscInt b = points[2 * p]; 7108 PetscInt c, r, k; 7109 PetscInt dof; 7110 7111 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7112 if (!dof) { 7113 continue; 7114 } 7115 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7116 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7117 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7118 7119 for (r = 0; r < numIndices; r++) { 7120 for (c = 0; c < nCols; c++) { 7121 for (k = 0; k < dof; k++) { 7122 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7123 } 7124 } 7125 } 7126 } 7127 else { 7128 /* copy this column as is */ 7129 for (r = 0; r < numIndices; r++) { 7130 for (c = 0; c < dof; c++) { 7131 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7132 } 7133 } 7134 } 7135 oldOff += dof; 7136 } 7137 } 7138 7139 if (multiplyLeft) { 7140 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 7141 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 7142 /* multiply constraints transpose on the left */ 7143 if (numFields) { 7144 for (f = 0; f < numFields; f++) { 7145 PetscInt oldOff = offsets[f]; 7146 7147 for (p = 0; p < numPoints; p++) { 7148 PetscInt rStart = newPointOffsets[f][p]; 7149 PetscInt b = points[2 * p]; 7150 PetscInt c, r, k; 7151 PetscInt dof; 7152 7153 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7154 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7155 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7156 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7157 7158 for (r = 0; r < nRows; r++) { 7159 for (c = 0; c < newNumIndices; c++) { 7160 for (k = 0; k < dof; k++) { 7161 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7162 } 7163 } 7164 } 7165 } 7166 else { 7167 /* copy this row as is */ 7168 for (r = 0; r < dof; r++) { 7169 for (c = 0; c < newNumIndices; c++) { 7170 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7171 } 7172 } 7173 } 7174 oldOff += dof; 7175 } 7176 } 7177 } 7178 else { 7179 PetscInt oldOff = 0; 7180 7181 for (p = 0; p < numPoints; p++) { 7182 PetscInt rStart = newPointOffsets[0][p]; 7183 PetscInt b = points[2 * p]; 7184 PetscInt c, r, k; 7185 PetscInt dof; 7186 7187 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7188 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7189 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7190 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7191 7192 for (r = 0; r < nRows; r++) { 7193 for (c = 0; c < newNumIndices; c++) { 7194 for (k = 0; k < dof; k++) { 7195 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7196 } 7197 } 7198 } 7199 } 7200 else { 7201 /* copy this row as is */ 7202 for (r = 0; r < dof; r++) { 7203 for (c = 0; c < newNumIndices; c++) { 7204 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7205 } 7206 } 7207 } 7208 oldOff += dof; 7209 } 7210 } 7211 7212 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7213 } 7214 else { 7215 newValues = tmpValues; 7216 } 7217 } 7218 7219 /* clean up */ 7220 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7221 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7222 7223 if (numFields) { 7224 for (f = 0; f < numFields; f++) { 7225 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7226 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7227 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7228 } 7229 } 7230 else { 7231 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7232 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7233 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7234 } 7235 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7236 7237 /* output */ 7238 if (outPoints) { 7239 *outPoints = newPoints; 7240 } 7241 else { 7242 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7243 } 7244 if (outValues) { 7245 *outValues = newValues; 7246 } 7247 for (f = 0; f <= numFields; f++) { 7248 offsets[f] = newOffsets[f]; 7249 } 7250 PetscFunctionReturn(0); 7251 } 7252 7253 /*@C 7254 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7255 7256 Not collective 7257 7258 Input Parameters: 7259 + dm - The DM 7260 . section - The PetscSection describing the points (a local section) 7261 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7262 . point - The point defining the closure 7263 - useClPerm - Use the closure point permutation if available 7264 7265 Output Parameters: 7266 + numIndices - The number of dof indices in the closure of point with the input sections 7267 . indices - The dof indices 7268 . outOffsets - Array to write the field offsets into, or NULL 7269 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7270 7271 Notes: 7272 Must call DMPlexRestoreClosureIndices() to free allocated memory 7273 7274 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7275 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7276 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7277 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7278 indices (with the above semantics) are implied. 7279 7280 Level: advanced 7281 7282 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7283 @*/ 7284 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7285 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7286 { 7287 /* Closure ordering */ 7288 PetscSection clSection; 7289 IS clPoints; 7290 const PetscInt *clp; 7291 PetscInt *points; 7292 const PetscInt *clperm = NULL; 7293 /* Dof permutation and sign flips */ 7294 const PetscInt **perms[32] = {NULL}; 7295 const PetscScalar **flips[32] = {NULL}; 7296 PetscScalar *valCopy = NULL; 7297 /* Hanging node constraints */ 7298 PetscInt *pointsC = NULL; 7299 PetscScalar *valuesC = NULL; 7300 PetscInt NclC, NiC; 7301 7302 PetscInt *idx; 7303 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7304 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7305 PetscErrorCode ierr; 7306 7307 PetscFunctionBeginHot; 7308 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7309 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7310 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7311 if (numIndices) PetscValidPointer(numIndices, 6); 7312 if (indices) PetscValidPointer(indices, 7); 7313 if (outOffsets) PetscValidPointer(outOffsets, 8); 7314 if (values) PetscValidPointer(values, 9); 7315 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7316 PetscCheckFalse(Nf > 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7317 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7318 /* 1) Get points in closure */ 7319 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7320 if (useClPerm) { 7321 PetscInt depth, clsize; 7322 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7323 for (clsize=0,p=0; p<Ncl; p++) { 7324 PetscInt dof; 7325 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7326 clsize += dof; 7327 } 7328 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7329 } 7330 /* 2) Get number of indices on these points and field offsets from section */ 7331 for (p = 0; p < Ncl*2; p += 2) { 7332 PetscInt dof, fdof; 7333 7334 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7335 for (f = 0; f < Nf; ++f) { 7336 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7337 offsets[f+1] += fdof; 7338 } 7339 Ni += dof; 7340 } 7341 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7342 PetscCheckFalse(Nf && offsets[Nf] != Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7343 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7344 for (f = 0; f < PetscMax(1, Nf); ++f) { 7345 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7346 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7347 /* may need to apply sign changes to the element matrix */ 7348 if (values && flips[f]) { 7349 PetscInt foffset = offsets[f]; 7350 7351 for (p = 0; p < Ncl; ++p) { 7352 PetscInt pnt = points[2*p], fdof; 7353 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7354 7355 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7356 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7357 if (flip) { 7358 PetscInt i, j, k; 7359 7360 if (!valCopy) { 7361 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7362 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7363 *values = valCopy; 7364 } 7365 for (i = 0; i < fdof; ++i) { 7366 PetscScalar fval = flip[i]; 7367 7368 for (k = 0; k < Ni; ++k) { 7369 valCopy[Ni * (foffset + i) + k] *= fval; 7370 valCopy[Ni * k + (foffset + i)] *= fval; 7371 } 7372 } 7373 } 7374 foffset += fdof; 7375 } 7376 } 7377 } 7378 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7379 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7380 if (NclC) { 7381 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7382 for (f = 0; f < PetscMax(1, Nf); ++f) { 7383 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7384 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7385 } 7386 for (f = 0; f < PetscMax(1, Nf); ++f) { 7387 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7388 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7389 } 7390 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7391 Ncl = NclC; 7392 Ni = NiC; 7393 points = pointsC; 7394 if (values) *values = valuesC; 7395 } 7396 /* 5) Calculate indices */ 7397 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7398 if (Nf) { 7399 PetscInt idxOff; 7400 PetscBool useFieldOffsets; 7401 7402 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7403 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7404 if (useFieldOffsets) { 7405 for (p = 0; p < Ncl; ++p) { 7406 const PetscInt pnt = points[p*2]; 7407 7408 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7409 } 7410 } else { 7411 for (p = 0; p < Ncl; ++p) { 7412 const PetscInt pnt = points[p*2]; 7413 7414 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7415 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7416 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7417 * global section. */ 7418 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7419 } 7420 } 7421 } else { 7422 PetscInt off = 0, idxOff; 7423 7424 for (p = 0; p < Ncl; ++p) { 7425 const PetscInt pnt = points[p*2]; 7426 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7427 7428 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7429 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7430 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7431 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7432 } 7433 } 7434 /* 6) Cleanup */ 7435 for (f = 0; f < PetscMax(1, Nf); ++f) { 7436 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7437 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7438 } 7439 if (NclC) { 7440 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7441 } else { 7442 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7443 } 7444 7445 if (numIndices) *numIndices = Ni; 7446 if (indices) *indices = idx; 7447 PetscFunctionReturn(0); 7448 } 7449 7450 /*@C 7451 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7452 7453 Not collective 7454 7455 Input Parameters: 7456 + dm - The DM 7457 . section - The PetscSection describing the points (a local section) 7458 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7459 . point - The point defining the closure 7460 - useClPerm - Use the closure point permutation if available 7461 7462 Output Parameters: 7463 + numIndices - The number of dof indices in the closure of point with the input sections 7464 . indices - The dof indices 7465 . outOffsets - Array to write the field offsets into, or NULL 7466 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7467 7468 Notes: 7469 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7470 7471 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7472 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7473 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7474 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7475 indices (with the above semantics) are implied. 7476 7477 Level: advanced 7478 7479 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7480 @*/ 7481 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7482 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7483 { 7484 PetscErrorCode ierr; 7485 7486 PetscFunctionBegin; 7487 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7488 PetscValidPointer(indices, 7); 7489 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7490 PetscFunctionReturn(0); 7491 } 7492 7493 /*@C 7494 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7495 7496 Not collective 7497 7498 Input Parameters: 7499 + dm - The DM 7500 . section - The section describing the layout in v, or NULL to use the default section 7501 . globalSection - The section describing the layout in v, or NULL to use the default global section 7502 . A - The matrix 7503 . point - The point in the DM 7504 . values - The array of values 7505 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7506 7507 Fortran Notes: 7508 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7509 7510 Level: intermediate 7511 7512 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7513 @*/ 7514 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7515 { 7516 DM_Plex *mesh = (DM_Plex*) dm->data; 7517 PetscInt *indices; 7518 PetscInt numIndices; 7519 const PetscScalar *valuesOrig = values; 7520 PetscErrorCode ierr; 7521 7522 PetscFunctionBegin; 7523 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7524 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7525 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7526 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7527 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7528 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7529 7530 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7531 7532 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7533 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7534 if (ierr) { 7535 PetscMPIInt rank; 7536 PetscErrorCode ierr2; 7537 7538 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7539 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7540 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7541 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7542 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7543 SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7544 } 7545 if (mesh->printFEM > 1) { 7546 PetscInt i; 7547 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7548 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7549 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7550 } 7551 7552 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7553 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7554 PetscFunctionReturn(0); 7555 } 7556 7557 /*@C 7558 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7559 7560 Not collective 7561 7562 Input Parameters: 7563 + dmRow - The DM for the row fields 7564 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7565 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7566 . dmCol - The DM for the column fields 7567 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7568 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7569 . A - The matrix 7570 . point - The point in the DMs 7571 . values - The array of values 7572 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7573 7574 Level: intermediate 7575 7576 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7577 @*/ 7578 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7579 { 7580 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7581 PetscInt *indicesRow, *indicesCol; 7582 PetscInt numIndicesRow, numIndicesCol; 7583 const PetscScalar *valuesOrig = values; 7584 PetscErrorCode ierr; 7585 7586 PetscFunctionBegin; 7587 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7588 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7589 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7590 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7591 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7592 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7593 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7594 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7595 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7596 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7597 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7598 7599 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7600 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7601 7602 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7603 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7604 if (ierr) { 7605 PetscMPIInt rank; 7606 PetscErrorCode ierr2; 7607 7608 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7609 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7610 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7611 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7612 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7613 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7614 CHKERRQ(ierr); 7615 } 7616 7617 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7618 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7619 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7620 PetscFunctionReturn(0); 7621 } 7622 7623 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7624 { 7625 DM_Plex *mesh = (DM_Plex*) dmf->data; 7626 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7627 PetscInt *cpoints = NULL; 7628 PetscInt *findices, *cindices; 7629 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7630 PetscInt foffsets[32], coffsets[32]; 7631 DMPolytopeType ct; 7632 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7633 PetscErrorCode ierr; 7634 7635 PetscFunctionBegin; 7636 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7637 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7638 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7639 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7640 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7641 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7642 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7643 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7644 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7645 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7646 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7647 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7648 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7649 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7650 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7651 /* Column indices */ 7652 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7653 maxFPoints = numCPoints; 7654 /* Compress out points not in the section */ 7655 /* TODO: Squeeze out points with 0 dof as well */ 7656 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7657 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7658 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7659 cpoints[q*2] = cpoints[p]; 7660 cpoints[q*2+1] = cpoints[p+1]; 7661 ++q; 7662 } 7663 } 7664 numCPoints = q; 7665 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7666 PetscInt fdof; 7667 7668 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7669 if (!dof) continue; 7670 for (f = 0; f < numFields; ++f) { 7671 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7672 coffsets[f+1] += fdof; 7673 } 7674 numCIndices += dof; 7675 } 7676 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7677 /* Row indices */ 7678 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7679 { 7680 DMPlexTransform tr; 7681 DMPolytopeType *rct; 7682 PetscInt *rsize, *rcone, *rornt, Nt; 7683 7684 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7685 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7686 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7687 numSubcells = rsize[Nt-1]; 7688 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7689 } 7690 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7691 for (r = 0, q = 0; r < numSubcells; ++r) { 7692 /* TODO Map from coarse to fine cells */ 7693 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7694 /* Compress out points not in the section */ 7695 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7696 for (p = 0; p < numFPoints*2; p += 2) { 7697 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7698 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7699 if (!dof) continue; 7700 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7701 if (s < q) continue; 7702 ftotpoints[q*2] = fpoints[p]; 7703 ftotpoints[q*2+1] = fpoints[p+1]; 7704 ++q; 7705 } 7706 } 7707 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7708 } 7709 numFPoints = q; 7710 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7711 PetscInt fdof; 7712 7713 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7714 if (!dof) continue; 7715 for (f = 0; f < numFields; ++f) { 7716 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7717 foffsets[f+1] += fdof; 7718 } 7719 numFIndices += dof; 7720 } 7721 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7722 7723 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7724 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7725 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7726 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7727 if (numFields) { 7728 const PetscInt **permsF[32] = {NULL}; 7729 const PetscInt **permsC[32] = {NULL}; 7730 7731 for (f = 0; f < numFields; f++) { 7732 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7733 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7734 } 7735 for (p = 0; p < numFPoints; p++) { 7736 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7737 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7738 } 7739 for (p = 0; p < numCPoints; p++) { 7740 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7741 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7742 } 7743 for (f = 0; f < numFields; f++) { 7744 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7745 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7746 } 7747 } else { 7748 const PetscInt **permsF = NULL; 7749 const PetscInt **permsC = NULL; 7750 7751 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7752 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7753 for (p = 0, off = 0; p < numFPoints; p++) { 7754 const PetscInt *perm = permsF ? permsF[p] : NULL; 7755 7756 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7757 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7758 } 7759 for (p = 0, off = 0; p < numCPoints; p++) { 7760 const PetscInt *perm = permsC ? permsC[p] : NULL; 7761 7762 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7763 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7764 } 7765 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7766 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7767 } 7768 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7769 /* TODO: flips */ 7770 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7771 if (ierr) { 7772 PetscMPIInt rank; 7773 PetscErrorCode ierr2; 7774 7775 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7776 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7777 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7778 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7779 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7780 CHKERRQ(ierr); 7781 } 7782 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7783 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7784 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7785 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7786 PetscFunctionReturn(0); 7787 } 7788 7789 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7790 { 7791 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7792 PetscInt *cpoints = NULL; 7793 PetscInt foffsets[32], coffsets[32]; 7794 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7795 DMPolytopeType ct; 7796 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7797 PetscErrorCode ierr; 7798 7799 PetscFunctionBegin; 7800 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7801 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7802 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7803 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7804 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7805 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7806 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7807 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7808 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7809 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7810 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7811 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7812 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7813 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7814 /* Column indices */ 7815 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7816 maxFPoints = numCPoints; 7817 /* Compress out points not in the section */ 7818 /* TODO: Squeeze out points with 0 dof as well */ 7819 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7820 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7821 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7822 cpoints[q*2] = cpoints[p]; 7823 cpoints[q*2+1] = cpoints[p+1]; 7824 ++q; 7825 } 7826 } 7827 numCPoints = q; 7828 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7829 PetscInt fdof; 7830 7831 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7832 if (!dof) continue; 7833 for (f = 0; f < numFields; ++f) { 7834 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7835 coffsets[f+1] += fdof; 7836 } 7837 numCIndices += dof; 7838 } 7839 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7840 /* Row indices */ 7841 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7842 { 7843 DMPlexTransform tr; 7844 DMPolytopeType *rct; 7845 PetscInt *rsize, *rcone, *rornt, Nt; 7846 7847 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7848 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7849 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7850 numSubcells = rsize[Nt-1]; 7851 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7852 } 7853 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7854 for (r = 0, q = 0; r < numSubcells; ++r) { 7855 /* TODO Map from coarse to fine cells */ 7856 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7857 /* Compress out points not in the section */ 7858 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7859 for (p = 0; p < numFPoints*2; p += 2) { 7860 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7861 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7862 if (!dof) continue; 7863 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7864 if (s < q) continue; 7865 ftotpoints[q*2] = fpoints[p]; 7866 ftotpoints[q*2+1] = fpoints[p+1]; 7867 ++q; 7868 } 7869 } 7870 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7871 } 7872 numFPoints = q; 7873 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7874 PetscInt fdof; 7875 7876 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7877 if (!dof) continue; 7878 for (f = 0; f < numFields; ++f) { 7879 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7880 foffsets[f+1] += fdof; 7881 } 7882 numFIndices += dof; 7883 } 7884 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7885 7886 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7887 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7888 if (numFields) { 7889 const PetscInt **permsF[32] = {NULL}; 7890 const PetscInt **permsC[32] = {NULL}; 7891 7892 for (f = 0; f < numFields; f++) { 7893 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7894 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7895 } 7896 for (p = 0; p < numFPoints; p++) { 7897 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7898 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7899 } 7900 for (p = 0; p < numCPoints; p++) { 7901 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7902 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7903 } 7904 for (f = 0; f < numFields; f++) { 7905 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7906 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7907 } 7908 } else { 7909 const PetscInt **permsF = NULL; 7910 const PetscInt **permsC = NULL; 7911 7912 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7913 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7914 for (p = 0, off = 0; p < numFPoints; p++) { 7915 const PetscInt *perm = permsF ? permsF[p] : NULL; 7916 7917 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7918 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7919 } 7920 for (p = 0, off = 0; p < numCPoints; p++) { 7921 const PetscInt *perm = permsC ? permsC[p] : NULL; 7922 7923 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7924 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7925 } 7926 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7927 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7928 } 7929 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7930 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7931 PetscFunctionReturn(0); 7932 } 7933 7934 /*@C 7935 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7936 7937 Input Parameter: 7938 . dm - The DMPlex object 7939 7940 Output Parameter: 7941 . cellHeight - The height of a cell 7942 7943 Level: developer 7944 7945 .seealso DMPlexSetVTKCellHeight() 7946 @*/ 7947 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7948 { 7949 DM_Plex *mesh = (DM_Plex*) dm->data; 7950 7951 PetscFunctionBegin; 7952 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7953 PetscValidPointer(cellHeight, 2); 7954 *cellHeight = mesh->vtkCellHeight; 7955 PetscFunctionReturn(0); 7956 } 7957 7958 /*@C 7959 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7960 7961 Input Parameters: 7962 + dm - The DMPlex object 7963 - cellHeight - The height of a cell 7964 7965 Level: developer 7966 7967 .seealso DMPlexGetVTKCellHeight() 7968 @*/ 7969 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7970 { 7971 DM_Plex *mesh = (DM_Plex*) dm->data; 7972 7973 PetscFunctionBegin; 7974 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7975 mesh->vtkCellHeight = cellHeight; 7976 PetscFunctionReturn(0); 7977 } 7978 7979 /*@ 7980 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7981 7982 Input Parameter: 7983 . dm - The DMPlex object 7984 7985 Output Parameters: 7986 + gcStart - The first ghost cell, or NULL 7987 - gcEnd - The upper bound on ghost cells, or NULL 7988 7989 Level: advanced 7990 7991 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 7992 @*/ 7993 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7994 { 7995 DMLabel ctLabel; 7996 PetscErrorCode ierr; 7997 7998 PetscFunctionBegin; 7999 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8000 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 8001 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 8002 PetscFunctionReturn(0); 8003 } 8004 8005 /* We can easily have a form that takes an IS instead */ 8006 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8007 { 8008 PetscSection section, globalSection; 8009 PetscInt *numbers, p; 8010 PetscErrorCode ierr; 8011 8012 PetscFunctionBegin; 8013 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8014 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 8015 for (p = pStart; p < pEnd; ++p) { 8016 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 8017 } 8018 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 8019 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8020 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 8021 for (p = pStart; p < pEnd; ++p) { 8022 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 8023 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8024 else numbers[p-pStart] += shift; 8025 } 8026 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 8027 if (globalSize) { 8028 PetscLayout layout; 8029 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 8030 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 8031 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 8032 } 8033 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8034 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8035 PetscFunctionReturn(0); 8036 } 8037 8038 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8039 { 8040 PetscInt cellHeight, cStart, cEnd; 8041 PetscErrorCode ierr; 8042 8043 PetscFunctionBegin; 8044 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8045 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8046 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8047 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 8048 PetscFunctionReturn(0); 8049 } 8050 8051 /*@ 8052 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 8053 8054 Input Parameter: 8055 . dm - The DMPlex object 8056 8057 Output Parameter: 8058 . globalCellNumbers - Global cell numbers for all cells on this process 8059 8060 Level: developer 8061 8062 .seealso DMPlexGetVertexNumbering() 8063 @*/ 8064 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8065 { 8066 DM_Plex *mesh = (DM_Plex*) dm->data; 8067 PetscErrorCode ierr; 8068 8069 PetscFunctionBegin; 8070 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8071 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 8072 *globalCellNumbers = mesh->globalCellNumbers; 8073 PetscFunctionReturn(0); 8074 } 8075 8076 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8077 { 8078 PetscInt vStart, vEnd; 8079 PetscErrorCode ierr; 8080 8081 PetscFunctionBegin; 8082 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8083 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8084 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 8085 PetscFunctionReturn(0); 8086 } 8087 8088 /*@ 8089 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 8090 8091 Input Parameter: 8092 . dm - The DMPlex object 8093 8094 Output Parameter: 8095 . globalVertexNumbers - Global vertex numbers for all vertices on this process 8096 8097 Level: developer 8098 8099 .seealso DMPlexGetCellNumbering() 8100 @*/ 8101 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8102 { 8103 DM_Plex *mesh = (DM_Plex*) dm->data; 8104 PetscErrorCode ierr; 8105 8106 PetscFunctionBegin; 8107 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8108 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 8109 *globalVertexNumbers = mesh->globalVertexNumbers; 8110 PetscFunctionReturn(0); 8111 } 8112 8113 /*@ 8114 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 8115 8116 Input Parameter: 8117 . dm - The DMPlex object 8118 8119 Output Parameter: 8120 . globalPointNumbers - Global numbers for all points on this process 8121 8122 Level: developer 8123 8124 .seealso DMPlexGetCellNumbering() 8125 @*/ 8126 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8127 { 8128 IS nums[4]; 8129 PetscInt depths[4], gdepths[4], starts[4]; 8130 PetscInt depth, d, shift = 0; 8131 PetscErrorCode ierr; 8132 8133 PetscFunctionBegin; 8134 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8135 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8136 /* For unstratified meshes use dim instead of depth */ 8137 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 8138 for (d = 0; d <= depth; ++d) { 8139 PetscInt end; 8140 8141 depths[d] = depth-d; 8142 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 8143 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8144 } 8145 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 8146 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8147 for (d = 0; d <= depth; ++d) { 8148 PetscCheckFalse(starts[d] >= 0 && depths[d] != gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8149 } 8150 for (d = 0; d <= depth; ++d) { 8151 PetscInt pStart, pEnd, gsize; 8152 8153 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 8154 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 8155 shift += gsize; 8156 } 8157 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 8158 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 8159 PetscFunctionReturn(0); 8160 } 8161 8162 /*@ 8163 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 8164 8165 Input Parameter: 8166 . dm - The DMPlex object 8167 8168 Output Parameter: 8169 . ranks - The rank field 8170 8171 Options Database Keys: 8172 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 8173 8174 Level: intermediate 8175 8176 .seealso: DMView() 8177 @*/ 8178 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8179 { 8180 DM rdm; 8181 PetscFE fe; 8182 PetscScalar *r; 8183 PetscMPIInt rank; 8184 DMPolytopeType ct; 8185 PetscInt dim, cStart, cEnd, c; 8186 PetscBool simplex; 8187 PetscErrorCode ierr; 8188 8189 PetscFunctionBeginUser; 8190 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8191 PetscValidPointer(ranks, 2); 8192 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 8193 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8194 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8195 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8196 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 8197 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 8198 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 8199 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 8200 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8201 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8202 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8203 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 8204 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 8205 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 8206 for (c = cStart; c < cEnd; ++c) { 8207 PetscScalar *lr; 8208 8209 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 8210 if (lr) *lr = rank; 8211 } 8212 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8213 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8214 PetscFunctionReturn(0); 8215 } 8216 8217 /*@ 8218 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8219 8220 Input Parameters: 8221 + dm - The DMPlex 8222 - label - The DMLabel 8223 8224 Output Parameter: 8225 . val - The label value field 8226 8227 Options Database Keys: 8228 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8229 8230 Level: intermediate 8231 8232 .seealso: DMView() 8233 @*/ 8234 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8235 { 8236 DM rdm; 8237 PetscFE fe; 8238 PetscScalar *v; 8239 PetscInt dim, cStart, cEnd, c; 8240 PetscErrorCode ierr; 8241 8242 PetscFunctionBeginUser; 8243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8244 PetscValidPointer(label, 2); 8245 PetscValidPointer(val, 3); 8246 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8247 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8248 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8249 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8250 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8251 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8252 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8253 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8254 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8255 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8256 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8257 for (c = cStart; c < cEnd; ++c) { 8258 PetscScalar *lv; 8259 PetscInt cval; 8260 8261 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8262 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8263 *lv = cval; 8264 } 8265 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8266 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8267 PetscFunctionReturn(0); 8268 } 8269 8270 /*@ 8271 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8272 8273 Input Parameter: 8274 . dm - The DMPlex object 8275 8276 Notes: 8277 This is a useful diagnostic when creating meshes programmatically. 8278 8279 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8280 8281 Level: developer 8282 8283 .seealso: DMCreate(), DMSetFromOptions() 8284 @*/ 8285 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8286 { 8287 PetscSection coneSection, supportSection; 8288 const PetscInt *cone, *support; 8289 PetscInt coneSize, c, supportSize, s; 8290 PetscInt pStart, pEnd, p, pp, csize, ssize; 8291 PetscBool storagecheck = PETSC_TRUE; 8292 PetscErrorCode ierr; 8293 8294 PetscFunctionBegin; 8295 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8296 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8297 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8298 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8299 /* Check that point p is found in the support of its cone points, and vice versa */ 8300 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8301 for (p = pStart; p < pEnd; ++p) { 8302 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8303 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8304 for (c = 0; c < coneSize; ++c) { 8305 PetscBool dup = PETSC_FALSE; 8306 PetscInt d; 8307 for (d = c-1; d >= 0; --d) { 8308 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8309 } 8310 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8311 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8312 for (s = 0; s < supportSize; ++s) { 8313 if (support[s] == p) break; 8314 } 8315 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8316 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8317 for (s = 0; s < coneSize; ++s) { 8318 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8319 } 8320 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8321 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8322 for (s = 0; s < supportSize; ++s) { 8323 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8324 } 8325 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8326 PetscCheckFalse(dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8327 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8328 } 8329 } 8330 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8331 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8332 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8333 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8334 for (s = 0; s < supportSize; ++s) { 8335 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8336 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8337 for (c = 0; c < coneSize; ++c) { 8338 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8339 if (cone[c] != pp) { c = 0; break; } 8340 if (cone[c] == p) break; 8341 } 8342 if (c >= coneSize) { 8343 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8344 for (c = 0; c < supportSize; ++c) { 8345 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8346 } 8347 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8348 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8349 for (c = 0; c < coneSize; ++c) { 8350 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8351 } 8352 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8353 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8354 } 8355 } 8356 } 8357 if (storagecheck) { 8358 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8359 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8360 PetscCheckFalse(csize != ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8361 } 8362 PetscFunctionReturn(0); 8363 } 8364 8365 /* 8366 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. 8367 */ 8368 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8369 { 8370 DMPolytopeType cct; 8371 PetscInt ptpoints[4]; 8372 const PetscInt *cone, *ccone, *ptcone; 8373 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8374 PetscErrorCode ierr; 8375 8376 PetscFunctionBegin; 8377 *unsplit = 0; 8378 switch (ct) { 8379 case DM_POLYTOPE_POINT_PRISM_TENSOR: 8380 ptpoints[npt++] = c; 8381 break; 8382 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8383 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8384 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8385 for (cp = 0; cp < coneSize; ++cp) { 8386 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8387 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8388 } 8389 break; 8390 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8391 case DM_POLYTOPE_QUAD_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 = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8396 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8397 for (ccp = 0; ccp < cconeSize; ++ccp) { 8398 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8399 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8400 PetscInt p; 8401 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8402 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8403 } 8404 } 8405 } 8406 break; 8407 default: break; 8408 } 8409 for (pt = 0; pt < npt; ++pt) { 8410 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8411 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8412 } 8413 PetscFunctionReturn(0); 8414 } 8415 8416 /*@ 8417 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8418 8419 Input Parameters: 8420 + dm - The DMPlex object 8421 - cellHeight - Normally 0 8422 8423 Notes: 8424 This is a useful diagnostic when creating meshes programmatically. 8425 Currently applicable only to homogeneous simplex or tensor meshes. 8426 8427 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8428 8429 Level: developer 8430 8431 .seealso: DMCreate(), DMSetFromOptions() 8432 @*/ 8433 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8434 { 8435 DMPlexInterpolatedFlag interp; 8436 DMPolytopeType ct; 8437 PetscInt vStart, vEnd, cStart, cEnd, c; 8438 PetscErrorCode ierr; 8439 8440 PetscFunctionBegin; 8441 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8442 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8443 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8444 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8445 for (c = cStart; c < cEnd; ++c) { 8446 PetscInt *closure = NULL; 8447 PetscInt coneSize, closureSize, cl, Nv = 0; 8448 8449 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8450 PetscCheckFalse((PetscInt) ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8451 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8452 if (interp == DMPLEX_INTERPOLATED_FULL) { 8453 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8454 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)); 8455 } 8456 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8457 for (cl = 0; cl < closureSize*2; cl += 2) { 8458 const PetscInt p = closure[cl]; 8459 if ((p >= vStart) && (p < vEnd)) ++Nv; 8460 } 8461 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8462 /* Special Case: Tensor faces with identified vertices */ 8463 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8464 PetscInt unsplit; 8465 8466 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8467 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8468 } 8469 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)); 8470 } 8471 PetscFunctionReturn(0); 8472 } 8473 8474 /*@ 8475 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8476 8477 Not Collective 8478 8479 Input Parameters: 8480 + dm - The DMPlex object 8481 - cellHeight - Normally 0 8482 8483 Notes: 8484 This is a useful diagnostic when creating meshes programmatically. 8485 This routine is only relevant for meshes that are fully interpolated across all ranks. 8486 It will error out if a partially interpolated mesh is given on some rank. 8487 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8488 8489 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8490 8491 Level: developer 8492 8493 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8494 @*/ 8495 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8496 { 8497 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8498 PetscErrorCode ierr; 8499 DMPlexInterpolatedFlag interpEnum; 8500 8501 PetscFunctionBegin; 8502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8503 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8504 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8505 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8506 PetscMPIInt rank; 8507 MPI_Comm comm; 8508 8509 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8510 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8511 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8512 } 8513 8514 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8515 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8516 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8517 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8518 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8519 for (c = cStart; c < cEnd; ++c) { 8520 const PetscInt *cone, *ornt, *faceSizes, *faces; 8521 const DMPolytopeType *faceTypes; 8522 DMPolytopeType ct; 8523 PetscInt numFaces, coneSize, f; 8524 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8525 8526 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8527 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8528 if (unsplit) continue; 8529 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8530 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8531 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8532 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8533 for (cl = 0; cl < closureSize*2; cl += 2) { 8534 const PetscInt p = closure[cl]; 8535 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8536 } 8537 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8538 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); 8539 for (f = 0; f < numFaces; ++f) { 8540 DMPolytopeType fct; 8541 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8542 8543 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8544 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8545 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8546 const PetscInt p = fclosure[cl]; 8547 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8548 } 8549 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]); 8550 for (v = 0; v < fnumCorners; ++v) { 8551 if (fclosure[v] != faces[fOff+v]) { 8552 PetscInt v1; 8553 8554 ierr = PetscPrintf(PETSC_COMM_SELF, "face closure:");CHKERRQ(ierr); 8555 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]);CHKERRQ(ierr);} 8556 ierr = PetscPrintf(PETSC_COMM_SELF, "\ncell face:");CHKERRQ(ierr); 8557 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]);CHKERRQ(ierr);} 8558 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8559 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]); 8560 } 8561 } 8562 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8563 fOff += faceSizes[f]; 8564 } 8565 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8566 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8567 } 8568 } 8569 PetscFunctionReturn(0); 8570 } 8571 8572 /*@ 8573 DMPlexCheckGeometry - Check the geometry of mesh cells 8574 8575 Input Parameter: 8576 . dm - The DMPlex object 8577 8578 Notes: 8579 This is a useful diagnostic when creating meshes programmatically. 8580 8581 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8582 8583 Level: developer 8584 8585 .seealso: DMCreate(), DMSetFromOptions() 8586 @*/ 8587 PetscErrorCode DMPlexCheckGeometry(DM dm) 8588 { 8589 Vec coordinates; 8590 PetscReal detJ, J[9], refVol = 1.0; 8591 PetscReal vol; 8592 PetscBool periodic; 8593 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8594 PetscErrorCode ierr; 8595 8596 PetscFunctionBegin; 8597 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8598 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8599 if (dim != dE) PetscFunctionReturn(0); 8600 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8601 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8602 for (d = 0; d < dim; ++d) refVol *= 2.0; 8603 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8604 /* Make sure local coordinates are created, because that step is collective */ 8605 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8606 for (c = cStart; c < cEnd; ++c) { 8607 DMPolytopeType ct; 8608 PetscInt unsplit; 8609 PetscBool ignoreZeroVol = PETSC_FALSE; 8610 8611 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8612 switch (ct) { 8613 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8614 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8615 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8616 ignoreZeroVol = PETSC_TRUE; break; 8617 default: break; 8618 } 8619 switch (ct) { 8620 case DM_POLYTOPE_TRI_PRISM: 8621 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8622 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8623 case DM_POLYTOPE_PYRAMID: 8624 continue; 8625 default: break; 8626 } 8627 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8628 if (unsplit) continue; 8629 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8630 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); 8631 ierr = PetscInfo(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8632 if (depth > 1 && !periodic) { 8633 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8634 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); 8635 ierr = PetscInfo(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8636 } 8637 } 8638 PetscFunctionReturn(0); 8639 } 8640 8641 /*@ 8642 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8643 8644 Input Parameters: 8645 . dm - The DMPlex object 8646 8647 Notes: 8648 This is mainly intended for debugging/testing purposes. 8649 It currently checks only meshes with no partition overlapping. 8650 8651 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8652 8653 Level: developer 8654 8655 .seealso: DMGetPointSF(), DMSetFromOptions() 8656 @*/ 8657 PetscErrorCode DMPlexCheckPointSF(DM dm) 8658 { 8659 PetscSF pointSF; 8660 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8661 const PetscInt *locals, *rootdegree; 8662 PetscBool distributed; 8663 PetscErrorCode ierr; 8664 8665 PetscFunctionBegin; 8666 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8667 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8668 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8669 if (!distributed) PetscFunctionReturn(0); 8670 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8671 if (overlap) { 8672 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8673 PetscFunctionReturn(0); 8674 } 8675 PetscCheckFalse(!pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8676 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8677 PetscCheckFalse(nroots < 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8678 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8679 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8680 8681 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8682 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8683 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8684 for (l = 0; l < nleaves; ++l) { 8685 const PetscInt point = locals[l]; 8686 8687 PetscCheckFalse(point >= cStart && point < cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8688 } 8689 8690 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8691 for (l = 0; l < nleaves; ++l) { 8692 const PetscInt point = locals[l]; 8693 const PetscInt *cone; 8694 PetscInt coneSize, c, idx; 8695 8696 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8697 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8698 for (c = 0; c < coneSize; ++c) { 8699 if (!rootdegree[cone[c]]) { 8700 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8701 PetscCheckFalse(idx < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8702 } 8703 } 8704 } 8705 PetscFunctionReturn(0); 8706 } 8707 8708 PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8709 { 8710 PetscErrorCode ierr; 8711 8712 PetscFunctionBegin; 8713 ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr); 8714 ierr = DMPlexCheckSkeleton(dm, cellHeight);CHKERRQ(ierr); 8715 ierr = DMPlexCheckFaces(dm, cellHeight);CHKERRQ(ierr); 8716 ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr); 8717 ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 8718 ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr); 8719 PetscFunctionReturn(0); 8720 } 8721 8722 typedef struct cell_stats 8723 { 8724 PetscReal min, max, sum, squaresum; 8725 PetscInt count; 8726 } cell_stats_t; 8727 8728 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8729 { 8730 PetscInt i, N = *len; 8731 8732 for (i = 0; i < N; i++) { 8733 cell_stats_t *A = (cell_stats_t *) a; 8734 cell_stats_t *B = (cell_stats_t *) b; 8735 8736 B->min = PetscMin(A->min,B->min); 8737 B->max = PetscMax(A->max,B->max); 8738 B->sum += A->sum; 8739 B->squaresum += A->squaresum; 8740 B->count += A->count; 8741 } 8742 } 8743 8744 /*@ 8745 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8746 8747 Collective on dm 8748 8749 Input Parameters: 8750 + dm - The DMPlex object 8751 . output - If true, statistics will be displayed on stdout 8752 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8753 8754 Notes: 8755 This is mainly intended for debugging/testing purposes. 8756 8757 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8758 8759 Level: developer 8760 8761 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8762 @*/ 8763 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8764 { 8765 DM dmCoarse; 8766 cell_stats_t stats, globalStats; 8767 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8768 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8769 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8770 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8771 PetscMPIInt rank,size; 8772 PetscErrorCode ierr; 8773 8774 PetscFunctionBegin; 8775 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8776 stats.min = PETSC_MAX_REAL; 8777 stats.max = PETSC_MIN_REAL; 8778 stats.sum = stats.squaresum = 0.; 8779 stats.count = 0; 8780 8781 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8782 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8783 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8784 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8785 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8786 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8787 for (c = cStart; c < cEnd; c++) { 8788 PetscInt i; 8789 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8790 8791 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8792 PetscCheckFalse(detJ < 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8793 for (i = 0; i < PetscSqr(cdim); ++i) { 8794 frobJ += J[i] * J[i]; 8795 frobInvJ += invJ[i] * invJ[i]; 8796 } 8797 cond2 = frobJ * frobInvJ; 8798 cond = PetscSqrtReal(cond2); 8799 8800 stats.min = PetscMin(stats.min,cond); 8801 stats.max = PetscMax(stats.max,cond); 8802 stats.sum += cond; 8803 stats.squaresum += cond2; 8804 stats.count++; 8805 if (output && cond > limit) { 8806 PetscSection coordSection; 8807 Vec coordsLocal; 8808 PetscScalar *coords = NULL; 8809 PetscInt Nv, d, clSize, cl, *closure = NULL; 8810 8811 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8812 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8813 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8814 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8815 for (i = 0; i < Nv/cdim; ++i) { 8816 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8817 for (d = 0; d < cdim; ++d) { 8818 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8819 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8820 } 8821 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8822 } 8823 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8824 for (cl = 0; cl < clSize*2; cl += 2) { 8825 const PetscInt edge = closure[cl]; 8826 8827 if ((edge >= eStart) && (edge < eEnd)) { 8828 PetscReal len; 8829 8830 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8831 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8832 } 8833 } 8834 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8835 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8836 } 8837 } 8838 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8839 8840 if (size > 1) { 8841 PetscMPIInt blockLengths[2] = {4,1}; 8842 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8843 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8844 MPI_Op statReduce; 8845 8846 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8847 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8848 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8849 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8850 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8851 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8852 } else { 8853 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8854 } 8855 if (rank == 0) { 8856 count = globalStats.count; 8857 min = globalStats.min; 8858 max = globalStats.max; 8859 mean = globalStats.sum / globalStats.count; 8860 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8861 } 8862 8863 if (output) { 8864 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); 8865 } 8866 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8867 8868 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8869 if (dmCoarse) { 8870 PetscBool isplex; 8871 8872 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8873 if (isplex) { 8874 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8875 } 8876 } 8877 PetscFunctionReturn(0); 8878 } 8879 8880 /*@ 8881 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8882 orthogonal quality below given tolerance. 8883 8884 Collective on dm 8885 8886 Input Parameters: 8887 + dm - The DMPlex object 8888 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8889 - atol - [0, 1] Absolute tolerance for tagging cells. 8890 8891 Output Parameters: 8892 + OrthQual - Vec containing orthogonal quality per cell 8893 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8894 8895 Options Database Keys: 8896 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8897 supported. 8898 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8899 8900 Notes: 8901 Orthogonal quality is given by the following formula: 8902 8903 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8904 8905 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 8906 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8907 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8908 calculating the cosine of the angle between these vectors. 8909 8910 Orthogonal quality ranges from 1 (best) to 0 (worst). 8911 8912 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8913 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8914 8915 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8916 8917 Level: intermediate 8918 8919 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8920 @*/ 8921 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8922 { 8923 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8924 PetscInt *idx; 8925 PetscScalar *oqVals; 8926 const PetscScalar *cellGeomArr, *faceGeomArr; 8927 PetscReal *ci, *fi, *Ai; 8928 MPI_Comm comm; 8929 Vec cellgeom, facegeom; 8930 DM dmFace, dmCell; 8931 IS glob; 8932 ISLocalToGlobalMapping ltog; 8933 PetscViewer vwr; 8934 PetscErrorCode ierr; 8935 8936 PetscFunctionBegin; 8937 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8938 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8939 PetscValidPointer(OrthQual, 4); 8940 PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 8941 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8942 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8943 PetscCheckFalse(nc < 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8944 { 8945 DMPlexInterpolatedFlag interpFlag; 8946 8947 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8948 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8949 PetscMPIInt rank; 8950 8951 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8952 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8953 } 8954 } 8955 if (OrthQualLabel) { 8956 PetscValidPointer(OrthQualLabel, 5); 8957 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8958 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8959 } else {*OrthQualLabel = NULL;} 8960 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8961 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8962 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8963 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8964 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8965 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8966 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8967 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8968 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8969 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8970 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8971 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8972 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8973 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8974 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8975 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8976 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8977 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8978 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8979 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8980 PetscInt cellarr[2], *adj = NULL; 8981 PetscScalar *cArr, *fArr; 8982 PetscReal minvalc = 1.0, minvalf = 1.0; 8983 PetscFVCellGeom *cg; 8984 8985 idx[cellIter] = cell-cStart; 8986 cellarr[0] = cell; 8987 /* Make indexing into cellGeom easier */ 8988 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 8989 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 8990 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 8991 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 8992 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 8993 PetscInt i; 8994 const PetscInt neigh = adj[cellneigh]; 8995 PetscReal normci = 0, normfi = 0, normai = 0; 8996 PetscFVCellGeom *cgneigh; 8997 PetscFVFaceGeom *fg; 8998 8999 /* Don't count ourselves in the neighbor list */ 9000 if (neigh == cell) continue; 9001 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 9002 cellarr[1] = neigh; 9003 { 9004 PetscInt numcovpts; 9005 const PetscInt *covpts; 9006 9007 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9008 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 9009 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9010 } 9011 9012 /* Compute c_i, f_i and their norms */ 9013 for (i = 0; i < nc; i++) { 9014 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9015 fi[i] = fg->centroid[i] - cg->centroid[i]; 9016 Ai[i] = fg->normal[i]; 9017 normci += PetscPowReal(ci[i], 2); 9018 normfi += PetscPowReal(fi[i], 2); 9019 normai += PetscPowReal(Ai[i], 2); 9020 } 9021 normci = PetscSqrtReal(normci); 9022 normfi = PetscSqrtReal(normfi); 9023 normai = PetscSqrtReal(normai); 9024 9025 /* Normalize and compute for each face-cell-normal pair */ 9026 for (i = 0; i < nc; i++) { 9027 ci[i] = ci[i]/normci; 9028 fi[i] = fi[i]/normfi; 9029 Ai[i] = Ai[i]/normai; 9030 /* PetscAbs because I don't know if normals are guaranteed to point out */ 9031 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9032 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9033 } 9034 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9035 minvalc = PetscRealPart(cArr[cellneighiter]); 9036 } 9037 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9038 minvalf = PetscRealPart(fArr[cellneighiter]); 9039 } 9040 } 9041 ierr = PetscFree(adj);CHKERRQ(ierr); 9042 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 9043 /* Defer to cell if they're equal */ 9044 oqVals[cellIter] = PetscMin(minvalf, minvalc); 9045 if (OrthQualLabel) { 9046 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 9047 } 9048 } 9049 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 9050 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 9051 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 9052 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 9053 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 9054 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 9055 if (OrthQualLabel) { 9056 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 9057 } 9058 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 9059 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 9060 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 9061 PetscFunctionReturn(0); 9062 } 9063 9064 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 9065 * interpolator construction */ 9066 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9067 { 9068 PetscSection section, newSection, gsection; 9069 PetscSF sf; 9070 PetscBool hasConstraints, ghasConstraints; 9071 PetscErrorCode ierr; 9072 9073 PetscFunctionBegin; 9074 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9075 PetscValidPointer(odm,2); 9076 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9077 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 9078 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 9079 if (!ghasConstraints) { 9080 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 9081 *odm = dm; 9082 PetscFunctionReturn(0); 9083 } 9084 ierr = DMClone(dm, odm);CHKERRQ(ierr); 9085 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 9086 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 9087 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 9088 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 9089 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 9090 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 9091 PetscFunctionReturn(0); 9092 } 9093 9094 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9095 { 9096 DM dmco, dmfo; 9097 Mat interpo; 9098 Vec rscale; 9099 Vec cglobalo, clocal; 9100 Vec fglobal, fglobalo, flocal; 9101 PetscBool regular; 9102 PetscErrorCode ierr; 9103 9104 PetscFunctionBegin; 9105 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 9106 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 9107 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 9108 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 9109 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 9110 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 9111 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 9112 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 9113 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 9114 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 9115 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 9116 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 9117 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 9118 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 9119 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 9120 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 9121 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 9122 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9123 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9124 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 9125 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9126 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9127 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9128 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9129 *shift = fglobal; 9130 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 9131 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 9132 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 9133 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 9134 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9135 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 9136 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 9137 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 9138 PetscFunctionReturn(0); 9139 } 9140 9141 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9142 { 9143 PetscObject shifto; 9144 Vec shift; 9145 9146 PetscErrorCode ierr; 9147 9148 PetscFunctionBegin; 9149 if (!interp) { 9150 Vec rscale; 9151 9152 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 9153 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9154 } else { 9155 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 9156 } 9157 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 9158 if (!shifto) { 9159 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 9160 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 9161 shifto = (PetscObject) shift; 9162 ierr = VecDestroy(&shift);CHKERRQ(ierr); 9163 } 9164 shift = (Vec) shifto; 9165 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 9166 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 9167 ierr = MatDestroy(&interp);CHKERRQ(ierr); 9168 PetscFunctionReturn(0); 9169 } 9170 9171 /* Pointwise interpolation 9172 Just code FEM for now 9173 u^f = I u^c 9174 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 9175 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 9176 I_{ij} = psi^f_i phi^c_j 9177 */ 9178 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9179 { 9180 PetscSection gsc, gsf; 9181 PetscInt m, n; 9182 void *ctx; 9183 DM cdm; 9184 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9185 PetscErrorCode ierr; 9186 9187 PetscFunctionBegin; 9188 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9189 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9190 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9191 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9192 9193 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 9194 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 9195 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9196 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 9197 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9198 9199 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9200 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9201 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 9202 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 9203 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 9204 if (scaling) { 9205 /* Use naive scaling */ 9206 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 9207 } 9208 PetscFunctionReturn(0); 9209 } 9210 9211 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9212 { 9213 PetscErrorCode ierr; 9214 VecScatter ctx; 9215 9216 PetscFunctionBegin; 9217 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 9218 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 9219 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 9220 PetscFunctionReturn(0); 9221 } 9222 9223 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9224 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9225 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9226 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9227 { 9228 const PetscInt Nc = uOff[1] - uOff[0]; 9229 PetscInt c; 9230 for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 9231 } 9232 9233 PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9234 { 9235 DM dmc; 9236 PetscDS ds; 9237 Vec ones, locmass; 9238 IS cellIS; 9239 PetscFormKey key; 9240 PetscInt depth; 9241 PetscErrorCode ierr; 9242 9243 PetscFunctionBegin; 9244 ierr = DMClone(dm, &dmc);CHKERRQ(ierr); 9245 ierr = DMCopyDisc(dm, dmc);CHKERRQ(ierr); 9246 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9247 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9248 ierr = DMCreateGlobalVector(dmc, mass);CHKERRQ(ierr); 9249 ierr = DMGetLocalVector(dmc, &ones);CHKERRQ(ierr); 9250 ierr = DMGetLocalVector(dmc, &locmass);CHKERRQ(ierr); 9251 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9252 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9253 ierr = VecSet(locmass, 0.0);CHKERRQ(ierr); 9254 ierr = VecSet(ones, 1.0);CHKERRQ(ierr); 9255 key.label = NULL; 9256 key.value = 0; 9257 key.field = 0; 9258 key.part = 0; 9259 ierr = DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL);CHKERRQ(ierr); 9260 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9261 ierr = VecSet(*mass, 0.0);CHKERRQ(ierr); 9262 ierr = DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9263 ierr = DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9264 ierr = DMRestoreLocalVector(dmc, &ones);CHKERRQ(ierr); 9265 ierr = DMRestoreLocalVector(dmc, &locmass);CHKERRQ(ierr); 9266 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9267 PetscFunctionReturn(0); 9268 } 9269 9270 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9271 { 9272 PetscSection gsc, gsf; 9273 PetscInt m, n; 9274 void *ctx; 9275 DM cdm; 9276 PetscBool regular; 9277 PetscErrorCode ierr; 9278 9279 PetscFunctionBegin; 9280 if (dmFine == dmCoarse) { 9281 DM dmc; 9282 PetscDS ds; 9283 PetscWeakForm wf; 9284 Vec u; 9285 IS cellIS; 9286 PetscFormKey key; 9287 PetscInt depth; 9288 9289 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9290 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9291 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9292 ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 9293 ierr = PetscWeakFormClear(wf);CHKERRQ(ierr); 9294 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9295 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9296 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9297 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9298 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9299 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9300 key.label = NULL; 9301 key.value = 0; 9302 key.field = 0; 9303 key.part = 0; 9304 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9305 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9306 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9307 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9308 } else { 9309 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9310 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9311 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9312 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9313 9314 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9315 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9316 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9317 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9318 9319 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9320 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9321 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9322 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9323 } 9324 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9325 PetscFunctionReturn(0); 9326 } 9327 9328 /*@ 9329 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9330 9331 Input Parameter: 9332 . dm - The DMPlex object 9333 9334 Output Parameter: 9335 . regular - The flag 9336 9337 Level: intermediate 9338 9339 .seealso: DMPlexSetRegularRefinement() 9340 @*/ 9341 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9342 { 9343 PetscFunctionBegin; 9344 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9345 PetscValidPointer(regular, 2); 9346 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9347 PetscFunctionReturn(0); 9348 } 9349 9350 /*@ 9351 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9352 9353 Input Parameters: 9354 + dm - The DMPlex object 9355 - regular - The flag 9356 9357 Level: intermediate 9358 9359 .seealso: DMPlexGetRegularRefinement() 9360 @*/ 9361 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9362 { 9363 PetscFunctionBegin; 9364 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9365 ((DM_Plex *) dm->data)->regularRefinement = regular; 9366 PetscFunctionReturn(0); 9367 } 9368 9369 /* anchors */ 9370 /*@ 9371 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9372 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 9373 9374 not collective 9375 9376 Input Parameter: 9377 . dm - The DMPlex object 9378 9379 Output Parameters: 9380 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9381 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9382 9383 Level: intermediate 9384 9385 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 9386 @*/ 9387 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9388 { 9389 DM_Plex *plex = (DM_Plex *)dm->data; 9390 PetscErrorCode ierr; 9391 9392 PetscFunctionBegin; 9393 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9394 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9395 if (anchorSection) *anchorSection = plex->anchorSection; 9396 if (anchorIS) *anchorIS = plex->anchorIS; 9397 PetscFunctionReturn(0); 9398 } 9399 9400 /*@ 9401 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9402 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9403 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9404 9405 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9406 DMGetConstraints() and filling in the entries in the constraint matrix. 9407 9408 collective on dm 9409 9410 Input Parameters: 9411 + dm - The DMPlex object 9412 . 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). 9413 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9414 9415 The reference counts of anchorSection and anchorIS are incremented. 9416 9417 Level: intermediate 9418 9419 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 9420 @*/ 9421 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9422 { 9423 DM_Plex *plex = (DM_Plex *)dm->data; 9424 PetscMPIInt result; 9425 PetscErrorCode ierr; 9426 9427 PetscFunctionBegin; 9428 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9429 if (anchorSection) { 9430 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9431 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9432 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9433 } 9434 if (anchorIS) { 9435 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9436 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9437 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9438 } 9439 9440 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9441 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9442 plex->anchorSection = anchorSection; 9443 9444 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9445 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9446 plex->anchorIS = anchorIS; 9447 9448 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9449 PetscInt size, a, pStart, pEnd; 9450 const PetscInt *anchors; 9451 9452 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9453 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9454 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9455 for (a = 0; a < size; a++) { 9456 PetscInt p; 9457 9458 p = anchors[a]; 9459 if (p >= pStart && p < pEnd) { 9460 PetscInt dof; 9461 9462 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9463 if (dof) { 9464 PetscErrorCode ierr2; 9465 9466 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9467 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9468 } 9469 } 9470 } 9471 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9472 } 9473 /* reset the generic constraints */ 9474 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 9475 PetscFunctionReturn(0); 9476 } 9477 9478 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9479 { 9480 PetscSection anchorSection; 9481 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9482 PetscErrorCode ierr; 9483 9484 PetscFunctionBegin; 9485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9486 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9487 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9488 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9489 if (numFields) { 9490 PetscInt f; 9491 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9492 9493 for (f = 0; f < numFields; f++) { 9494 PetscInt numComp; 9495 9496 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9497 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9498 } 9499 } 9500 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9501 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9502 pStart = PetscMax(pStart,sStart); 9503 pEnd = PetscMin(pEnd,sEnd); 9504 pEnd = PetscMax(pStart,pEnd); 9505 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9506 for (p = pStart; p < pEnd; p++) { 9507 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9508 if (dof) { 9509 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9510 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9511 for (f = 0; f < numFields; f++) { 9512 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9513 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9514 } 9515 } 9516 } 9517 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9518 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9519 PetscFunctionReturn(0); 9520 } 9521 9522 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9523 { 9524 PetscSection aSec; 9525 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9526 const PetscInt *anchors; 9527 PetscInt numFields, f; 9528 IS aIS; 9529 PetscErrorCode ierr; 9530 MatType mtype; 9531 PetscBool iscuda,iskokkos; 9532 9533 PetscFunctionBegin; 9534 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9535 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9536 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9537 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9538 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9539 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9540 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9541 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9542 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9543 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9544 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9545 else mtype = MATSEQAIJ; 9546 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9547 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9548 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9549 /* cSec will be a subset of aSec and section */ 9550 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9551 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9552 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9553 i[0] = 0; 9554 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9555 for (p = pStart; p < pEnd; p++) { 9556 PetscInt rDof, rOff, r; 9557 9558 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9559 if (!rDof) continue; 9560 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9561 if (numFields) { 9562 for (f = 0; f < numFields; f++) { 9563 annz = 0; 9564 for (r = 0; r < rDof; r++) { 9565 a = anchors[rOff + r]; 9566 if (a < sStart || a >= sEnd) continue; 9567 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9568 annz += aDof; 9569 } 9570 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9571 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9572 for (q = 0; q < dof; q++) { 9573 i[off + q + 1] = i[off + q] + annz; 9574 } 9575 } 9576 } else { 9577 annz = 0; 9578 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9579 for (q = 0; q < dof; q++) { 9580 a = anchors[rOff + q]; 9581 if (a < sStart || a >= sEnd) continue; 9582 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9583 annz += aDof; 9584 } 9585 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9586 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9587 for (q = 0; q < dof; q++) { 9588 i[off + q + 1] = i[off + q] + annz; 9589 } 9590 } 9591 } 9592 nnz = i[m]; 9593 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9594 offset = 0; 9595 for (p = pStart; p < pEnd; p++) { 9596 if (numFields) { 9597 for (f = 0; f < numFields; f++) { 9598 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9599 for (q = 0; q < dof; q++) { 9600 PetscInt rDof, rOff, r; 9601 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9602 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9603 for (r = 0; r < rDof; r++) { 9604 PetscInt s; 9605 9606 a = anchors[rOff + r]; 9607 if (a < sStart || a >= sEnd) continue; 9608 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9609 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9610 for (s = 0; s < aDof; s++) { 9611 j[offset++] = aOff + s; 9612 } 9613 } 9614 } 9615 } 9616 } else { 9617 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9618 for (q = 0; q < dof; q++) { 9619 PetscInt rDof, rOff, r; 9620 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9621 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9622 for (r = 0; r < rDof; r++) { 9623 PetscInt s; 9624 9625 a = anchors[rOff + r]; 9626 if (a < sStart || a >= sEnd) continue; 9627 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9628 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9629 for (s = 0; s < aDof; s++) { 9630 j[offset++] = aOff + s; 9631 } 9632 } 9633 } 9634 } 9635 } 9636 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9637 ierr = PetscFree(i);CHKERRQ(ierr); 9638 ierr = PetscFree(j);CHKERRQ(ierr); 9639 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9640 PetscFunctionReturn(0); 9641 } 9642 9643 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9644 { 9645 DM_Plex *plex = (DM_Plex *)dm->data; 9646 PetscSection anchorSection, section, cSec; 9647 Mat cMat; 9648 PetscErrorCode ierr; 9649 9650 PetscFunctionBegin; 9651 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9652 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9653 if (anchorSection) { 9654 PetscInt Nf; 9655 9656 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9657 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9658 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9659 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9660 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9661 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 9662 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9663 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9664 } 9665 PetscFunctionReturn(0); 9666 } 9667 9668 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9669 { 9670 IS subis; 9671 PetscSection section, subsection; 9672 PetscErrorCode ierr; 9673 9674 PetscFunctionBegin; 9675 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9676 PetscCheckFalse(!section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9677 PetscCheckFalse(!subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9678 /* Create subdomain */ 9679 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9680 /* Create submodel */ 9681 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9682 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9683 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9684 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9685 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9686 /* Create map from submodel to global model */ 9687 if (is) { 9688 PetscSection sectionGlobal, subsectionGlobal; 9689 IS spIS; 9690 const PetscInt *spmap; 9691 PetscInt *subIndices; 9692 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9693 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9694 9695 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9696 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9697 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9698 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9699 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9700 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9701 for (p = pStart; p < pEnd; ++p) { 9702 PetscInt gdof, pSubSize = 0; 9703 9704 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9705 if (gdof > 0) { 9706 for (f = 0; f < Nf; ++f) { 9707 PetscInt fdof, fcdof; 9708 9709 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9710 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9711 pSubSize += fdof-fcdof; 9712 } 9713 subSize += pSubSize; 9714 if (pSubSize) { 9715 if (bs < 0) { 9716 bs = pSubSize; 9717 } else if (bs != pSubSize) { 9718 /* Layout does not admit a pointwise block size */ 9719 bs = 1; 9720 } 9721 } 9722 } 9723 } 9724 /* Must have same blocksize on all procs (some might have no points) */ 9725 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9726 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9727 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9728 else {bs = bsMinMax[0];} 9729 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9730 for (p = pStart; p < pEnd; ++p) { 9731 PetscInt gdof, goff; 9732 9733 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9734 if (gdof > 0) { 9735 const PetscInt point = spmap[p]; 9736 9737 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9738 for (f = 0; f < Nf; ++f) { 9739 PetscInt fdof, fcdof, fc, f2, poff = 0; 9740 9741 /* Can get rid of this loop by storing field information in the global section */ 9742 for (f2 = 0; f2 < f; ++f2) { 9743 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9744 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9745 poff += fdof-fcdof; 9746 } 9747 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9748 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9749 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9750 subIndices[subOff] = goff+poff+fc; 9751 } 9752 } 9753 } 9754 } 9755 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9756 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9757 if (bs > 1) { 9758 /* We need to check that the block size does not come from non-contiguous fields */ 9759 PetscInt i, j, set = 1; 9760 for (i = 0; i < subSize; i += bs) { 9761 for (j = 0; j < bs; ++j) { 9762 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9763 } 9764 } 9765 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9766 } 9767 /* Attach nullspace */ 9768 for (f = 0; f < Nf; ++f) { 9769 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9770 if ((*subdm)->nullspaceConstructors[f]) break; 9771 } 9772 if (f < Nf) { 9773 MatNullSpace nullSpace; 9774 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9775 9776 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9777 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9778 } 9779 } 9780 PetscFunctionReturn(0); 9781 } 9782 9783 /*@ 9784 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9785 9786 Input Parameter: 9787 - dm - The DM 9788 9789 Level: developer 9790 9791 Options Database Keys: 9792 . -dm_plex_monitor_throughput - Activate the monitor 9793 9794 .seealso: DMSetFromOptions(), DMPlexCreate() 9795 @*/ 9796 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9797 { 9798 #if defined(PETSC_USE_LOG) 9799 PetscStageLog stageLog; 9800 PetscLogEvent event; 9801 PetscLogStage stage; 9802 PetscEventPerfInfo eventInfo; 9803 PetscReal cellRate, flopRate; 9804 PetscInt cStart, cEnd, Nf, N; 9805 const char *name; 9806 PetscErrorCode ierr; 9807 #endif 9808 9809 PetscFunctionBegin; 9810 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9811 #if defined(PETSC_USE_LOG) 9812 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9813 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9814 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9815 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9816 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9817 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9818 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9819 N = (cEnd - cStart)*Nf*eventInfo.count; 9820 flopRate = eventInfo.flops/eventInfo.time; 9821 cellRate = N/eventInfo.time; 9822 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); 9823 #else 9824 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9825 #endif 9826 PetscFunctionReturn(0); 9827 } 9828