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