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